mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 14:45:29 +00:00
789 lines
29 KiB
C++
789 lines
29 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
* vim: set ts=2 sw=2 et tw=78:
|
|
* 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/.
|
|
*
|
|
* This Original Code has been modified by IBM Corporation.
|
|
* Modifications made by IBM described herein are
|
|
* Copyright (c) International Business Machines
|
|
* Corporation, 2000
|
|
*
|
|
* Modifications to Mozilla code or documentation
|
|
* identified per MPL Section 3.3
|
|
*
|
|
* Date Modified by Description of modification
|
|
* 05/03/2000 IBM Corp. Observer events for reflow states
|
|
*/
|
|
|
|
/* a presentation of a document, part 2 */
|
|
|
|
#ifndef nsPresShell_h_
|
|
#define nsPresShell_h_
|
|
|
|
#include "nsIPresShell.h"
|
|
#include "nsStubDocumentObserver.h"
|
|
#include "nsISelectionController.h"
|
|
#include "nsIObserver.h"
|
|
#include "nsWeakReference.h"
|
|
#include "nsCRT.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsIWidget.h"
|
|
#include "nsStyleSet.h"
|
|
#include "nsPresArena.h"
|
|
#include "nsFrameSelection.h"
|
|
#include "nsGUIEvent.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsRefreshDriver.h"
|
|
#include "mozilla/Attributes.h"
|
|
|
|
class nsRange;
|
|
class nsIDragService;
|
|
class nsCSSStyleSheet;
|
|
|
|
struct RangePaintInfo;
|
|
struct nsCallbackEventRequest;
|
|
#ifdef MOZ_REFLOW_PERF
|
|
class ReflowCountMgr;
|
|
#endif
|
|
|
|
class nsPresShellEventCB;
|
|
class nsAutoCauseReflowNotifier;
|
|
|
|
// 250ms. This is actually pref-controlled, but we use this value if we fail
|
|
// to get the pref for any reason.
|
|
#define PAINTLOCK_EVENT_DELAY 250
|
|
|
|
class PresShell : public nsIPresShell,
|
|
public nsStubDocumentObserver,
|
|
public nsISelectionController, public nsIObserver,
|
|
public nsSupportsWeakReference
|
|
{
|
|
public:
|
|
PresShell();
|
|
|
|
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
|
|
|
// nsISupports
|
|
NS_DECL_ISUPPORTS
|
|
|
|
// nsIPresShell
|
|
virtual NS_HIDDEN_(nsresult) Init(nsIDocument* aDocument,
|
|
nsPresContext* aPresContext,
|
|
nsIViewManager* aViewManager,
|
|
nsStyleSet* aStyleSet,
|
|
nsCompatibility aCompatMode);
|
|
virtual NS_HIDDEN_(void) Destroy();
|
|
|
|
virtual NS_HIDDEN_(nsresult) SetPreferenceStyleRules(bool aForceReflow);
|
|
|
|
NS_IMETHOD GetSelection(SelectionType aType, nsISelection** aSelection);
|
|
virtual nsISelection* GetCurrentSelection(SelectionType aType);
|
|
|
|
NS_IMETHOD SetDisplaySelection(int16_t aToggle);
|
|
NS_IMETHOD GetDisplaySelection(int16_t *aToggle);
|
|
NS_IMETHOD ScrollSelectionIntoView(SelectionType aType, SelectionRegion aRegion,
|
|
int16_t aFlags);
|
|
NS_IMETHOD RepaintSelection(SelectionType aType);
|
|
|
|
virtual NS_HIDDEN_(void) BeginObservingDocument();
|
|
virtual NS_HIDDEN_(void) EndObservingDocument();
|
|
virtual NS_HIDDEN_(nsresult) InitialReflow(nscoord aWidth, nscoord aHeight);
|
|
virtual NS_HIDDEN_(nsresult) ResizeReflow(nscoord aWidth, nscoord aHeight);
|
|
virtual NS_HIDDEN_(nsresult) ResizeReflowOverride(nscoord aWidth, nscoord aHeight);
|
|
virtual NS_HIDDEN_(void) StyleChangeReflow();
|
|
virtual NS_HIDDEN_(nsIPageSequenceFrame*) GetPageSequenceFrame() const;
|
|
virtual NS_HIDDEN_(nsIFrame*) GetRealPrimaryFrameFor(nsIContent* aContent) const;
|
|
|
|
virtual NS_HIDDEN_(nsIFrame*) GetPlaceholderFrameFor(nsIFrame* aFrame) const;
|
|
virtual NS_HIDDEN_(void) FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
|
|
nsFrameState aBitToAdd);
|
|
virtual NS_HIDDEN_(void) FrameNeedsToContinueReflow(nsIFrame *aFrame);
|
|
virtual NS_HIDDEN_(void) CancelAllPendingReflows();
|
|
virtual NS_HIDDEN_(bool) IsSafeToFlush() const;
|
|
virtual NS_HIDDEN_(void) FlushPendingNotifications(mozFlushType aType);
|
|
|
|
/**
|
|
* Recreates the frames for a node
|
|
*/
|
|
virtual NS_HIDDEN_(nsresult) RecreateFramesFor(nsIContent* aContent);
|
|
|
|
/**
|
|
* Post a callback that should be handled after reflow has finished.
|
|
*/
|
|
virtual NS_HIDDEN_(nsresult) PostReflowCallback(nsIReflowCallback* aCallback);
|
|
virtual NS_HIDDEN_(void) CancelReflowCallback(nsIReflowCallback* aCallback);
|
|
|
|
virtual NS_HIDDEN_(void) ClearFrameRefs(nsIFrame* aFrame);
|
|
virtual NS_HIDDEN_(already_AddRefed<nsRenderingContext>) GetReferenceRenderingContext();
|
|
virtual NS_HIDDEN_(nsresult) GoToAnchor(const nsAString& aAnchorName, bool aScroll);
|
|
virtual NS_HIDDEN_(nsresult) ScrollToAnchor();
|
|
|
|
virtual NS_HIDDEN_(nsresult) ScrollContentIntoView(nsIContent* aContent,
|
|
ScrollAxis aVertical,
|
|
ScrollAxis aHorizontal,
|
|
uint32_t aFlags);
|
|
virtual bool ScrollFrameRectIntoView(nsIFrame* aFrame,
|
|
const nsRect& aRect,
|
|
ScrollAxis aVertical,
|
|
ScrollAxis aHorizontal,
|
|
uint32_t aFlags);
|
|
virtual nsRectVisibility GetRectVisibility(nsIFrame *aFrame,
|
|
const nsRect &aRect,
|
|
nscoord aMinTwips) const;
|
|
|
|
virtual NS_HIDDEN_(void) SetIgnoreFrameDestruction(bool aIgnore);
|
|
virtual NS_HIDDEN_(void) NotifyDestroyingFrame(nsIFrame* aFrame);
|
|
|
|
virtual NS_HIDDEN_(nsresult) CaptureHistoryState(nsILayoutHistoryState** aLayoutHistoryState, bool aLeavingPage);
|
|
|
|
virtual NS_HIDDEN_(void) UnsuppressPainting();
|
|
|
|
virtual nsresult GetAgentStyleSheets(nsCOMArray<nsIStyleSheet>& aSheets);
|
|
virtual nsresult SetAgentStyleSheets(const nsCOMArray<nsIStyleSheet>& aSheets);
|
|
|
|
virtual nsresult AddOverrideStyleSheet(nsIStyleSheet *aSheet);
|
|
virtual nsresult RemoveOverrideStyleSheet(nsIStyleSheet *aSheet);
|
|
|
|
virtual NS_HIDDEN_(nsresult) HandleEventWithTarget(nsEvent* aEvent, nsIFrame* aFrame,
|
|
nsIContent* aContent,
|
|
nsEventStatus* aStatus);
|
|
virtual NS_HIDDEN_(nsIFrame*) GetEventTargetFrame();
|
|
virtual NS_HIDDEN_(already_AddRefed<nsIContent>) GetEventTargetContent(nsEvent* aEvent);
|
|
|
|
|
|
virtual nsresult ReconstructFrames(void);
|
|
virtual void Freeze();
|
|
virtual void Thaw();
|
|
virtual void FireOrClearDelayedEvents(bool aFireEvents);
|
|
|
|
virtual NS_HIDDEN_(nsresult) RenderDocument(const nsRect& aRect, uint32_t aFlags,
|
|
nscolor aBackgroundColor,
|
|
gfxContext* aThebesContext);
|
|
|
|
virtual already_AddRefed<gfxASurface> RenderNode(nsIDOMNode* aNode,
|
|
nsIntRegion* aRegion,
|
|
nsIntPoint& aPoint,
|
|
nsIntRect* aScreenRect);
|
|
|
|
virtual already_AddRefed<gfxASurface> RenderSelection(nsISelection* aSelection,
|
|
nsIntPoint& aPoint,
|
|
nsIntRect* aScreenRect);
|
|
|
|
virtual already_AddRefed<nsPIDOMWindow> GetRootWindow();
|
|
|
|
virtual LayerManager* GetLayerManager();
|
|
|
|
virtual void SetIgnoreViewportScrolling(bool aIgnore);
|
|
|
|
virtual void SetDisplayPort(const nsRect& aDisplayPort);
|
|
|
|
virtual nsresult SetResolution(float aXResolution, float aYResolution);
|
|
|
|
//nsIViewObserver interface
|
|
|
|
virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion,
|
|
PaintType aType, bool aWillSendDidPaint);
|
|
virtual nsresult HandleEvent(nsIFrame* aFrame,
|
|
nsGUIEvent* aEvent,
|
|
bool aDontRetargetEvents,
|
|
nsEventStatus* aEventStatus);
|
|
virtual NS_HIDDEN_(nsresult) HandleDOMEventWithTarget(nsIContent* aTargetContent,
|
|
nsEvent* aEvent,
|
|
nsEventStatus* aStatus);
|
|
virtual NS_HIDDEN_(nsresult) HandleDOMEventWithTarget(nsIContent* aTargetContent,
|
|
nsIDOMEvent* aEvent,
|
|
nsEventStatus* aStatus);
|
|
virtual bool ShouldIgnoreInvalidation();
|
|
virtual void WillPaint(bool aWillSendDidPaint);
|
|
virtual void DidPaint();
|
|
virtual void ScheduleViewManagerFlush();
|
|
virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange);
|
|
virtual void ClearMouseCaptureOnView(nsIView* aView);
|
|
virtual bool IsVisible();
|
|
|
|
// caret handling
|
|
virtual NS_HIDDEN_(already_AddRefed<nsCaret>) GetCaret() const;
|
|
virtual NS_HIDDEN_(void) MaybeInvalidateCaretPosition();
|
|
NS_IMETHOD SetCaretEnabled(bool aInEnable);
|
|
NS_IMETHOD SetCaretReadOnly(bool aReadOnly);
|
|
NS_IMETHOD GetCaretEnabled(bool *aOutEnabled);
|
|
NS_IMETHOD SetCaretVisibilityDuringSelection(bool aVisibility);
|
|
NS_IMETHOD GetCaretVisible(bool *_retval);
|
|
virtual void SetCaret(nsCaret *aNewCaret);
|
|
virtual void RestoreCaret();
|
|
|
|
NS_IMETHOD SetSelectionFlags(int16_t aInEnable);
|
|
NS_IMETHOD GetSelectionFlags(int16_t *aOutEnable);
|
|
|
|
// nsISelectionController
|
|
|
|
NS_IMETHOD CharacterMove(bool aForward, bool aExtend);
|
|
NS_IMETHOD CharacterExtendForDelete();
|
|
NS_IMETHOD CharacterExtendForBackspace();
|
|
NS_IMETHOD WordMove(bool aForward, bool aExtend);
|
|
NS_IMETHOD WordExtendForDelete(bool aForward);
|
|
NS_IMETHOD LineMove(bool aForward, bool aExtend);
|
|
NS_IMETHOD IntraLineMove(bool aForward, bool aExtend);
|
|
NS_IMETHOD PageMove(bool aForward, bool aExtend);
|
|
NS_IMETHOD ScrollPage(bool aForward);
|
|
NS_IMETHOD ScrollLine(bool aForward);
|
|
NS_IMETHOD ScrollCharacter(bool aRight);
|
|
NS_IMETHOD CompleteScroll(bool aForward);
|
|
NS_IMETHOD CompleteMove(bool aForward, bool aExtend);
|
|
NS_IMETHOD SelectAll();
|
|
NS_IMETHOD CheckVisibility(nsIDOMNode *node, int16_t startOffset, int16_t EndOffset, bool *_retval);
|
|
virtual nsresult CheckVisibilityContent(nsIContent* aNode, int16_t aStartOffset,
|
|
int16_t aEndOffset, bool* aRetval);
|
|
|
|
// nsIDocumentObserver
|
|
NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE
|
|
NS_DECL_NSIDOCUMENTOBSERVER_ENDUPDATE
|
|
NS_DECL_NSIDOCUMENTOBSERVER_BEGINLOAD
|
|
NS_DECL_NSIDOCUMENTOBSERVER_ENDLOAD
|
|
NS_DECL_NSIDOCUMENTOBSERVER_CONTENTSTATECHANGED
|
|
NS_DECL_NSIDOCUMENTOBSERVER_DOCUMENTSTATESCHANGED
|
|
NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED
|
|
NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED
|
|
NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETAPPLICABLESTATECHANGED
|
|
NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED
|
|
NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED
|
|
NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEREMOVED
|
|
|
|
// 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
|
|
|
|
#ifdef MOZ_REFLOW_PERF
|
|
virtual NS_HIDDEN_(void) DumpReflows();
|
|
virtual NS_HIDDEN_(void) CountReflows(const char * aName, nsIFrame * aFrame);
|
|
virtual NS_HIDDEN_(void) PaintCount(const char * aName,
|
|
nsRenderingContext* aRenderingContext,
|
|
nsPresContext* aPresContext,
|
|
nsIFrame * aFrame,
|
|
const nsPoint& aOffset,
|
|
uint32_t aColor);
|
|
virtual NS_HIDDEN_(void) SetPaintFrameCount(bool aOn);
|
|
virtual bool IsPaintingFrameCounts();
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
virtual void ListStyleContexts(nsIFrame *aRootFrame, FILE *out,
|
|
int32_t aIndent = 0);
|
|
|
|
virtual void ListStyleSheets(FILE *out, int32_t aIndent = 0);
|
|
virtual void VerifyStyleTree();
|
|
#endif
|
|
|
|
#ifdef PR_LOGGING
|
|
static PRLogModuleInfo* gLog;
|
|
#endif
|
|
|
|
virtual NS_HIDDEN_(void) DisableNonTestMouseEvents(bool aDisable);
|
|
|
|
virtual void UpdateCanvasBackground();
|
|
|
|
virtual nsresult AddCanvasBackgroundColorItem(nsDisplayListBuilder& aBuilder,
|
|
nsDisplayList& aList,
|
|
nsIFrame* aFrame,
|
|
const nsRect& aBounds,
|
|
nscolor aBackstopColor,
|
|
uint32_t aFlags);
|
|
|
|
virtual nsresult AddPrintPreviewBackgroundItem(nsDisplayListBuilder& aBuilder,
|
|
nsDisplayList& aList,
|
|
nsIFrame* aFrame,
|
|
const nsRect& aBounds);
|
|
|
|
virtual nscolor ComputeBackstopColor(nsIView* aDisplayRoot);
|
|
|
|
virtual NS_HIDDEN_(nsresult) SetIsActive(bool aIsActive);
|
|
|
|
virtual bool GetIsViewportOverridden() { return mViewportOverridden; }
|
|
|
|
virtual bool IsLayoutFlushObserver()
|
|
{
|
|
return GetPresContext()->RefreshDriver()->
|
|
IsLayoutFlushObserver(this);
|
|
}
|
|
|
|
void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
|
nsArenaMemoryStats *aArenaObjectsSize,
|
|
size_t *aPresShellSize,
|
|
size_t *aStyleSetsSize,
|
|
size_t *aTextRunsSize,
|
|
size_t *aPresContextSize);
|
|
size_t SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) const;
|
|
|
|
// This data is stored as a content property (nsGkAtoms::scrolling) on
|
|
// mContentToScrollTo when we have a pending ScrollIntoView.
|
|
struct ScrollIntoViewData {
|
|
ScrollAxis mContentScrollVAxis;
|
|
ScrollAxis mContentScrollHAxis;
|
|
uint32_t mContentToScrollToFlags;
|
|
};
|
|
|
|
protected:
|
|
virtual ~PresShell();
|
|
|
|
void HandlePostedReflowCallbacks(bool aInterruptible);
|
|
void CancelPostedReflowCallbacks();
|
|
|
|
void UnsuppressAndInvalidate();
|
|
|
|
void WillCauseReflow() {
|
|
nsContentUtils::AddScriptBlocker();
|
|
++mChangeNestCount;
|
|
}
|
|
nsresult DidCauseReflow();
|
|
friend class nsAutoCauseReflowNotifier;
|
|
|
|
bool TouchesAreEqual(nsIDOMTouch *aTouch1, nsIDOMTouch *aTouch2);
|
|
void DispatchTouchEvent(nsEvent *aEvent,
|
|
nsEventStatus* aStatus,
|
|
nsPresShellEventCB* aEventCB,
|
|
bool aTouchIsNew);
|
|
|
|
void WillDoReflow();
|
|
void DidDoReflow(bool aInterruptible);
|
|
// ProcessReflowCommands returns whether we processed all our dirty roots
|
|
// without interruptions.
|
|
bool ProcessReflowCommands(bool aInterruptible);
|
|
// 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();
|
|
|
|
// Reflow regardless of whether the override bit has been set.
|
|
nsresult ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight);
|
|
|
|
// DoReflow returns whether the reflow finished without interruption
|
|
bool DoReflow(nsIFrame* aFrame, bool aInterruptible);
|
|
#ifdef DEBUG
|
|
void DoVerifyReflow();
|
|
void VerifyHasDirtyRootAncestor(nsIFrame* aFrame);
|
|
#endif
|
|
|
|
// Helper for ScrollContentIntoView
|
|
void DoScrollContentIntoView();
|
|
|
|
/**
|
|
* Initialize cached font inflation preference values.
|
|
*
|
|
* @see nsLayoutUtils::sFontSizeInflationEmPerLine
|
|
* @see nsLayoutUtils::sFontSizeInflationMinTwips
|
|
* @see nsLayoutUtils::sFontSizeInflationLineThreshold
|
|
*/
|
|
void SetupFontInflation();
|
|
|
|
friend struct AutoRenderingStateSaveRestore;
|
|
friend struct RenderingState;
|
|
|
|
struct RenderingState {
|
|
RenderingState(PresShell* aPresShell)
|
|
: mXResolution(aPresShell->mXResolution)
|
|
, mYResolution(aPresShell->mYResolution)
|
|
, mRenderFlags(aPresShell->mRenderFlags)
|
|
{ }
|
|
float mXResolution;
|
|
float mYResolution;
|
|
RenderFlags mRenderFlags;
|
|
};
|
|
|
|
struct AutoSaveRestoreRenderingState {
|
|
AutoSaveRestoreRenderingState(PresShell* aPresShell)
|
|
: mPresShell(aPresShell)
|
|
, mOldState(aPresShell)
|
|
{}
|
|
|
|
~AutoSaveRestoreRenderingState()
|
|
{
|
|
mPresShell->mRenderFlags = mOldState.mRenderFlags;
|
|
mPresShell->mXResolution = mOldState.mXResolution;
|
|
mPresShell->mYResolution = mOldState.mYResolution;
|
|
}
|
|
|
|
PresShell* mPresShell;
|
|
RenderingState mOldState;
|
|
};
|
|
static RenderFlags ChangeFlag(RenderFlags aFlags, bool aOnOff,
|
|
eRenderFlag aFlag)
|
|
{
|
|
return aOnOff ? (aFlags | aFlag) : (aFlag & ~aFlag);
|
|
}
|
|
|
|
|
|
void SetRenderingState(const RenderingState& aState);
|
|
|
|
friend class nsPresShellEventCB;
|
|
|
|
bool mCaretEnabled;
|
|
#ifdef DEBUG
|
|
nsStyleSet* CloneStyleSet(nsStyleSet* aSet);
|
|
bool VerifyIncrementalReflow();
|
|
bool mInVerifyReflow;
|
|
void ShowEventTargetDebug();
|
|
#endif
|
|
|
|
/**
|
|
* methods that manage rules that are used to implement the associated preferences
|
|
* - initially created for bugs 31816, 20760, 22963
|
|
*/
|
|
nsresult ClearPreferenceStyleRules(void);
|
|
nsresult CreatePreferenceStyleSheet(void);
|
|
nsresult SetPrefLinkRules(void);
|
|
nsresult SetPrefFocusRules(void);
|
|
nsresult SetPrefNoScriptRule();
|
|
nsresult SetPrefNoFramesRule(void);
|
|
|
|
// 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
|
|
RangePaintInfo* CreateRangePaintInfo(nsIDOMRange* 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
|
|
*/
|
|
already_AddRefed<gfxASurface>
|
|
PaintRangePaintInfo(nsTArray<nsAutoPtr<RangePaintInfo> >* aItems,
|
|
nsISelection* aSelection,
|
|
nsIntRegion* aRegion,
|
|
nsRect aArea,
|
|
nsIntPoint& aPoint,
|
|
nsIntRect* aScreenRect);
|
|
|
|
/**
|
|
* Methods to handle changes to user and UA sheet lists that we get
|
|
* notified about.
|
|
*/
|
|
void AddUserSheet(nsISupports* aSheet);
|
|
void AddAgentSheet(nsISupports* aSheet);
|
|
void RemoveSheet(nsStyleSet::sheetType aType, nsISupports* aSheet);
|
|
|
|
// Hide a view if it is a popup
|
|
void HideViewIfPopup(nsIView* aView);
|
|
|
|
// Utility method to restore the root scrollframe state
|
|
void RestoreRootScrollPosition();
|
|
|
|
void MaybeReleaseCapturingContent()
|
|
{
|
|
nsRefPtr<nsFrameSelection> frameSelection = FrameSelection();
|
|
if (frameSelection) {
|
|
frameSelection->SetMouseDownState(false);
|
|
}
|
|
if (gCaptureInfo.mContent &&
|
|
gCaptureInfo.mContent->OwnerDoc() == mDocument) {
|
|
SetCapturingContent(nullptr, 0);
|
|
}
|
|
}
|
|
|
|
nsresult HandleRetargetedEvent(nsEvent* aEvent, nsEventStatus* aStatus, nsIContent* aTarget)
|
|
{
|
|
PushCurrentEventInfo(nullptr, nullptr);
|
|
mCurrentEventContent = aTarget;
|
|
nsresult rv = NS_OK;
|
|
if (GetCurrentEventFrame()) {
|
|
rv = HandleEventInternal(aEvent, aStatus);
|
|
}
|
|
PopCurrentEventInfo();
|
|
return rv;
|
|
}
|
|
|
|
class nsDelayedEvent
|
|
{
|
|
public:
|
|
virtual ~nsDelayedEvent() {};
|
|
virtual void Dispatch(PresShell* aShell) {}
|
|
};
|
|
|
|
class nsDelayedInputEvent : public nsDelayedEvent
|
|
{
|
|
public:
|
|
virtual void Dispatch(PresShell* aShell)
|
|
{
|
|
if (mEvent && mEvent->widget) {
|
|
nsCOMPtr<nsIWidget> w = mEvent->widget;
|
|
nsEventStatus status;
|
|
w->DispatchEvent(mEvent, status);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
void Init(nsInputEvent* aEvent)
|
|
{
|
|
mEvent->time = aEvent->time;
|
|
mEvent->refPoint = aEvent->refPoint;
|
|
mEvent->modifiers = aEvent->modifiers;
|
|
}
|
|
|
|
nsDelayedInputEvent()
|
|
: nsDelayedEvent(), mEvent(nullptr) {}
|
|
|
|
nsInputEvent* mEvent;
|
|
};
|
|
|
|
class nsDelayedMouseEvent : public nsDelayedInputEvent
|
|
{
|
|
public:
|
|
nsDelayedMouseEvent(nsMouseEvent* aEvent) : nsDelayedInputEvent()
|
|
{
|
|
mEvent = new nsMouseEvent(NS_IS_TRUSTED_EVENT(aEvent),
|
|
aEvent->message,
|
|
aEvent->widget,
|
|
aEvent->reason,
|
|
aEvent->context);
|
|
Init(aEvent);
|
|
static_cast<nsMouseEvent*>(mEvent)->clickCount = aEvent->clickCount;
|
|
}
|
|
|
|
virtual ~nsDelayedMouseEvent()
|
|
{
|
|
delete static_cast<nsMouseEvent*>(mEvent);
|
|
}
|
|
};
|
|
|
|
class nsDelayedKeyEvent : public nsDelayedInputEvent
|
|
{
|
|
public:
|
|
nsDelayedKeyEvent(nsKeyEvent* aEvent) : nsDelayedInputEvent()
|
|
{
|
|
mEvent = new nsKeyEvent(NS_IS_TRUSTED_EVENT(aEvent),
|
|
aEvent->message,
|
|
aEvent->widget);
|
|
Init(aEvent);
|
|
static_cast<nsKeyEvent*>(mEvent)->keyCode = aEvent->keyCode;
|
|
static_cast<nsKeyEvent*>(mEvent)->charCode = aEvent->charCode;
|
|
static_cast<nsKeyEvent*>(mEvent)->alternativeCharCodes =
|
|
aEvent->alternativeCharCodes;
|
|
static_cast<nsKeyEvent*>(mEvent)->isChar = aEvent->isChar;
|
|
}
|
|
|
|
virtual ~nsDelayedKeyEvent()
|
|
{
|
|
delete static_cast<nsKeyEvent*>(mEvent);
|
|
}
|
|
};
|
|
|
|
// Check if aEvent is a mouse event and record the mouse location for later
|
|
// synth mouse moves.
|
|
void RecordMouseLocation(nsGUIEvent* aEvent);
|
|
class nsSynthMouseMoveEvent MOZ_FINAL : public nsARefreshObserver {
|
|
public:
|
|
nsSynthMouseMoveEvent(PresShell* aPresShell, bool aFromScroll)
|
|
: mPresShell(aPresShell), mFromScroll(aFromScroll) {
|
|
NS_ASSERTION(mPresShell, "null parameter");
|
|
}
|
|
~nsSynthMouseMoveEvent() {
|
|
Revoke();
|
|
}
|
|
|
|
NS_INLINE_DECL_REFCOUNTING(nsSynthMouseMoveEvent)
|
|
|
|
void Revoke() {
|
|
if (mPresShell) {
|
|
mPresShell->GetPresContext()->RefreshDriver()->
|
|
RemoveRefreshObserver(this, Flush_Display);
|
|
mPresShell = nullptr;
|
|
}
|
|
}
|
|
virtual void WillRefresh(mozilla::TimeStamp aTime) {
|
|
if (mPresShell)
|
|
mPresShell->ProcessSynthMouseMoveEvent(mFromScroll);
|
|
}
|
|
private:
|
|
PresShell* mPresShell;
|
|
bool mFromScroll;
|
|
};
|
|
void ProcessSynthMouseMoveEvent(bool aFromScroll);
|
|
|
|
void QueryIsActive();
|
|
nsresult UpdateImageLockingState();
|
|
|
|
#ifdef ANDROID
|
|
nsIDocument* GetTouchEventTargetDocument();
|
|
#endif
|
|
bool InZombieDocument(nsIContent *aContent);
|
|
already_AddRefed<nsIPresShell> GetParentPresShell();
|
|
nsIFrame* GetCurrentEventFrame();
|
|
nsresult RetargetEventToParent(nsGUIEvent* aEvent,
|
|
nsEventStatus* aEventStatus);
|
|
void PushCurrentEventInfo(nsIFrame* aFrame, nsIContent* aContent);
|
|
void PopCurrentEventInfo();
|
|
nsresult HandleEventInternal(nsEvent* aEvent, nsEventStatus *aStatus);
|
|
nsresult HandlePositionedEvent(nsIFrame* aTargetFrame,
|
|
nsGUIEvent* aEvent,
|
|
nsEventStatus* aEventStatus);
|
|
// 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<nsPIDOMWindow> GetFocusedDOMWindowInOurWindow();
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
bool AdjustContextMenuKeyEvent(nsMouseEvent* aEvent);
|
|
|
|
//
|
|
bool PrepareToUseCaretPosition(nsIWidget* aEventWidget, nsIntPoint& 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
|
|
void GetCurrentItemAndPositionForElement(nsIDOMElement *aCurrentEl,
|
|
nsIContent **aTargetToUse,
|
|
nsIntPoint& aTargetPt,
|
|
nsIWidget *aRootWidget);
|
|
|
|
void FireResizeEvent();
|
|
void FireBeforeResizeEvent();
|
|
static void AsyncResizeEventCallback(nsITimer* aTimer, void* aPresShell);
|
|
|
|
virtual void SynthesizeMouseMove(bool aFromScroll);
|
|
|
|
PresShell* GetRootPresShell();
|
|
|
|
nscolor GetDefaultBackgroundColorToDraw();
|
|
|
|
// The callback for the mPaintSuppressionTimer timer.
|
|
static void sPaintSuppressionCallback(nsITimer* aTimer, void* aPresShell);
|
|
|
|
// The callback for the mReflowContinueTimer timer.
|
|
static void sReflowContinueCallback(nsITimer* aTimer, void* aPresShell);
|
|
bool ScheduleReflowOffTimer();
|
|
|
|
// Widget notificiations
|
|
virtual void WindowSizeMoveDone();
|
|
virtual void SysColorChanged() { mPresContext->SysColorChanged(); }
|
|
virtual void ThemeChanged() { mPresContext->ThemeChanged(); }
|
|
|
|
#ifdef DEBUG
|
|
// The reflow root under which we're currently reflowing. Null when
|
|
// not in reflow.
|
|
nsIFrame* mCurrentReflowRoot;
|
|
uint32_t mUpdateCount;
|
|
#endif
|
|
|
|
#ifdef MOZ_REFLOW_PERF
|
|
ReflowCountMgr* mReflowCountMgr;
|
|
#endif
|
|
|
|
// 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. 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;
|
|
|
|
// mStyleSet owns it but we maintain a ref, may be null
|
|
nsRefPtr<nsCSSStyleSheet> mPrefStyleSheet;
|
|
|
|
// Set of frames that we should mark with NS_FRAME_HAS_DIRTY_CHILDREN after
|
|
// we finish reflowing mCurrentReflowRoot.
|
|
nsTHashtable<nsPtrHashKey<nsIFrame> > mFramesToDirty;
|
|
|
|
// Reflow roots that need to be reflowed.
|
|
nsTArray<nsIFrame*> mDirtyRoots;
|
|
|
|
nsTArray<nsAutoPtr<nsDelayedEvent> > mDelayedEvents;
|
|
nsRevocableEventPtr<nsRunnableMethod<PresShell> > mResizeEvent;
|
|
nsCOMPtr<nsITimer> mAsyncResizeEventTimer;
|
|
nsIFrame* mCurrentEventFrame;
|
|
nsCOMPtr<nsIContent> mCurrentEventContent;
|
|
nsTArray<nsIFrame*> mCurrentEventFrameStack;
|
|
nsCOMArray<nsIContent> mCurrentEventContentStack;
|
|
nsRevocableEventPtr<nsSynthMouseMoveEvent> mSynthMouseMoveEvent;
|
|
nsCOMPtr<nsIContent> mLastAnchorScrolledTo;
|
|
nsRefPtr<nsCaret> mCaret;
|
|
nsRefPtr<nsCaret> mOriginalCaret;
|
|
nsCallbackEventRequest* mFirstCallbackEventRequest;
|
|
nsCallbackEventRequest* mLastCallbackEventRequest;
|
|
|
|
// 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;
|
|
|
|
// 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;
|
|
|
|
// 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;
|
|
|
|
nscoord mLastAnchorScrollPositionY;
|
|
|
|
// 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;
|
|
|
|
bool mDocumentLoading : 1;
|
|
bool mIgnoreFrameDestruction : 1;
|
|
bool mHaveShutDown : 1;
|
|
bool mViewportOverridden : 1;
|
|
bool mLastRootReflowHadUnconstrainedHeight : 1;
|
|
bool mNoDelayedMouseEvents : 1;
|
|
bool mNoDelayedKeyEvents : 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;
|
|
|
|
// Indicates that it is safe to unlock painting once all pending reflows
|
|
// have been processed.
|
|
bool mShouldUnsuppressPainting : 1;
|
|
|
|
bool mAsyncResizeTimerIsActive : 1;
|
|
bool mInResize : 1;
|
|
|
|
static bool sDisableNonTestMouseEvents;
|
|
};
|
|
|
|
#endif /* !defined(nsPresShell_h_) */
|