Bug 526394. Part 31: Move scroll implementation into nsGfxScrollFrame. r=mats

This commit is contained in:
Robert O'Callahan 2009-10-08 16:01:15 +13:00
parent a8cbf01d74
commit 04a613495c
16 changed files with 977 additions and 676 deletions

View File

@ -2101,6 +2101,44 @@ nsPresContext::NotifyInvalidation(const nsRect& aRect, PRUint32 aFlags)
request->mFlags = aFlags;
}
void
nsPresContext::NotifyInvalidateRegion(const nsRegion& aRegion,
nsPoint aOffset, PRUint32 aFlags)
{
const nsRect* r;
for (nsRegionRectIterator iter(aRegion); (r = iter.Next());) {
NotifyInvalidation(*r + aOffset, aFlags);
}
}
void
nsPresContext::NotifyInvalidateForScrolling(const nsRegion& aBlitRegion,
const nsRegion& aInvalidateRegion)
{
nsPresContext* pc = this;
PRUint32 crossDocFlags = 0;
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
nsPoint offset(0,0);
while (pc) {
if (pc->MayHavePaintEventListener()) {
pc->NotifyInvalidateRegion(aBlitRegion, offset,
nsIFrame::INVALIDATE_REASON_SCROLL_BLIT | crossDocFlags);
pc->NotifyInvalidateRegion(aInvalidateRegion, offset,
nsIFrame::INVALIDATE_REASON_SCROLL_REPAINT | crossDocFlags);
}
crossDocFlags = nsIFrame::INVALIDATE_CROSS_DOC;
nsIFrame* rootParentFrame = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
if (!rootParentFrame)
break;
pc = rootParentFrame->PresContext();
nsIFrame* nextRootFrame = pc->PresShell()->FrameManager()->GetRootFrame();
offset += rootFrame->GetOffsetTo(nextRootFrame);
rootFrame = nextRootFrame;
}
}
PRBool
nsPresContext::HasCachedStyleData()
{

View File

@ -836,8 +836,9 @@ public:
// Returns true on success and false on failure (not safe).
PRBool EnsureSafeToHandOutCSSRules();
PRBool MayHavePaintEventListener();
void NotifyInvalidation(const nsRect& aRect, PRUint32 aFlags);
void NotifyInvalidateForScrolling(const nsRegion& aBlitRegion,
const nsRegion& aInvalidateRegion);
void FireDOMPaintEvent();
PRBool IsDOMPaintEventPending() {
return !mInvalidateRequests.mRequests.IsEmpty();
@ -955,6 +956,10 @@ protected:
NS_HIDDEN_(void) UpdateCharSet(const nsAFlatCString& aCharSet);
PRBool MayHavePaintEventListener();
void NotifyInvalidateRegion(const nsRegion& aRegion, nsPoint aOffset,
PRUint32 aFlags);
void HandleRebuildUserFontSet() {
mPostedFlushUserFontSet = PR_FALSE;
FlushUserFontSet();

View File

@ -802,9 +802,6 @@ public:
NS_IMETHOD ResizeReflow(nsIView *aView, nscoord aWidth, nscoord aHeight);
NS_IMETHOD_(PRBool) IsVisible();
NS_IMETHOD_(void) WillPaint();
NS_IMETHOD_(void) InvalidateFrameForScrolledView(nsIView *view);
NS_IMETHOD_(void) NotifyInvalidateForScrolledView(const nsRegion& aBlitRegion,
const nsRegion& aInvalidateRegion);
NS_IMETHOD_(void) DispatchSynthMouseMove(nsGUIEvent *aEvent,
PRBool aFlushOnHoverChange);
NS_IMETHOD_(void) ClearMouseCapture(nsIView* aView);
@ -4362,54 +4359,6 @@ PresShell::GetSelectionForCopy(nsISelection** outSelection)
return rv;
}
void
PresShell::InvalidateFrameForScrolledView(nsIView *aView)
{
nsIFrame* frame = nsLayoutUtils::GetFrameFor(aView);
if (!frame)
return;
frame->InvalidateWithFlags(frame->GetOverflowRect(),
nsIFrame::INVALIDATE_REASON_SCROLL_REPAINT);
}
static void
NotifyInvalidateRegion(nsPresContext* aPresContext, const nsRegion& aRegion,
nsPoint aOffset, PRUint32 aFlags)
{
const nsRect* r;
for (nsRegionRectIterator iter(aRegion); (r = iter.Next());) {
aPresContext->NotifyInvalidation(*r + aOffset, aFlags);
}
}
void
PresShell::NotifyInvalidateForScrolledView(const nsRegion& aBlitRegion,
const nsRegion& aInvalidateRegion)
{
nsPresContext* pc = GetPresContext();
PRUint32 crossDocFlags = 0;
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
nsPoint offset(0,0);
while (pc) {
if (pc->MayHavePaintEventListener()) {
NotifyInvalidateRegion(pc, aBlitRegion, offset,
nsIFrame::INVALIDATE_REASON_SCROLL_BLIT | crossDocFlags);
NotifyInvalidateRegion(pc, aInvalidateRegion, offset,
nsIFrame::INVALIDATE_REASON_SCROLL_REPAINT | crossDocFlags);
}
crossDocFlags = nsIFrame::INVALIDATE_CROSS_DOC;
nsIFrame* rootParentFrame = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
if (!rootParentFrame)
break;
pc = rootParentFrame->PresContext();
nsIFrame* nextRootFrame = pc->PresShell()->FrameManager()->GetRootFrame();
offset += rootFrame->GetOffsetTo(nextRootFrame);
rootFrame = nextRootFrame;
}
}
NS_IMETHODIMP_(void)
PresShell::DispatchSynthMouseMove(nsGUIEvent *aEvent,
PRBool aFlushOnHoverChange)

View File

@ -354,7 +354,7 @@ void nsListControlFrame::PaintFocus(nsIRenderingContext& aRC, nsPoint aPt)
fRect.MoveBy(childframe->GetParent()->GetOffsetTo(this));
} else {
fRect.x = fRect.y = 0;
fRect.width = GetScrollPortSize().width;
fRect.width = GetScrollPortRect().width;
fRect.height = CalcFallbackRowHeight();
fRect.MoveBy(containerFrame->GetOffsetTo(this));
}
@ -391,7 +391,7 @@ nsListControlFrame::InvalidateFocus()
// is drawn.
// The origin of the scrollport is the origin of containerFrame.
nsRect invalidateArea = containerFrame->GetOverflowRect();
nsRect emptyFallbackArea(0, 0, GetScrollPortSize().width, CalcFallbackRowHeight());
nsRect emptyFallbackArea(0, 0, GetScrollPortRect().width, CalcFallbackRowHeight());
invalidateArea.UnionRect(invalidateArea, emptyFallbackArea);
containerFrame->Invalidate(invalidateArea);
}

View File

@ -271,6 +271,11 @@ public:
*/
PRBool IsInDropDownMode() const;
/**
* Dropdowns need views
*/
virtual PRBool NeedsView() { return IsInDropDownMode(); }
/**
* Frees statics owned by this class.
*/

File diff suppressed because it is too large Load Diff

View File

@ -47,11 +47,13 @@
#include "nsIScrollPositionListener.h"
#include "nsIStatefulFrame.h"
#include "nsThreadUtils.h"
#include "nsIScrollableView.h"
#include "nsIView.h"
#include "nsIReflowCallback.h"
#include "nsBoxLayoutState.h"
#include "nsQueryFrame.h"
#include "nsCOMArray.h"
#ifdef MOZ_SVG
#include "nsSVGIntegrationUtils.h"
#endif
class nsPresContext;
class nsIPresShell;
@ -62,12 +64,9 @@ class nsIScrollFrameInternal;
class nsPresState;
struct ScrollReflowState;
class nsGfxScrollFrameInner : public nsIScrollPositionListener,
public nsIReflowCallback {
class nsGfxScrollFrameInner : public nsIReflowCallback {
public:
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void) { return 2; }
NS_IMETHOD_(nsrefcnt) Release(void) { return 1; }
class AsyncScroll;
nsGfxScrollFrameInner(nsContainerFrame* aOuter, PRBool aIsRoot,
PRBool aIsXUL);
@ -80,7 +79,6 @@ public:
// reload our child frame list.
// We need this if a scrollbar frame is recreated.
void ReloadChildFrames();
void CreateScrollableView();
nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
nsresult FireScrollPortEvent();
@ -95,12 +93,6 @@ public:
virtual PRBool ReflowFinished();
virtual void ReflowCallbackCanceled();
// nsIScrollPositionListener
NS_IMETHOD ScrollPositionWillChange(nscoord aX, nscoord aY);
virtual void ViewPositionDidChange(nsTArray<nsIWidget::Configuration>* aConfigurations);
NS_IMETHOD ScrollPositionDidChange(nscoord aX, nscoord aY);
// This gets called when the 'curpos' attribute on one of the scrollbars changes
void CurPosAttributeChanged(nsIContent* aChild);
void PostScrollEvent();
@ -136,24 +128,21 @@ public:
nscoord aSize);
nscoord GetCoordAttribute(nsIBox* aFrame, nsIAtom* atom, nscoord defaultValue);
// Like ScrollPositionDidChange, but initiated by this frame rather than from the
// scrolling view
void InternalScrollPositionDidChange(nscoord aX, nscoord aY);
// Update scrollbar curpos attributes to reflect current scroll position
void UpdateScrollbarPosition();
nsIScrollableView* GetScrollableView() const { return mScrollableView; }
nsRect GetScrollPortRect() const {
return mScrollableView->View()->GetBounds();
}
nsRect GetScrollPortRect() const { return mScrollPort; }
nsPoint GetScrollPosition() const {
nsPoint scrollPosition;
mScrollableView->GetScrollPosition(scrollPosition.x, scrollPosition.y);
return scrollPosition;
return mScrollPort.TopLeft() - mScrolledFrame->GetPosition();
}
nsRect GetScrollRange() const;
nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const;
nsPoint ClampAndRestrictToDevPixels(const nsPoint& aPt, nsIntPoint* aPtDevPx) const;
nsPoint ClampScrollPosition(const nsPoint& aPt) const;
static void AsyncScrollCallback(nsITimer *aTimer, void* anInstance);
void ScrollTo(nsPoint aScrollPosition, nsIScrollableFrame::ScrollMode aMode);
void ScrollToImpl(nsPoint aScrollPosition);
void ScrollVisual(nsIntPoint aPixDelta);
void ScrollBy(nsIntPoint aDelta, nsIScrollableFrame::ScrollUnit aUnit,
nsIScrollableFrame::ScrollMode aMode, nsIntPoint* aOverflow);
void ScrollToRestoredPosition();
@ -171,14 +160,12 @@ public:
}
void AddScrollPositionListener(nsIScrollPositionListener* aListener) {
mScrollableView->AddScrollPositionListener(aListener);
mListeners.AppendObject(aListener);
}
void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) {
mScrollableView->RemoveScrollPositionListener(aListener);
mListeners.RemoveObject(aListener);
}
void ScrollbarChanged(nsPresContext* aPresContext, nscoord aX, nscoord aY, PRUint32 aFlags);
static void SetScrollbarVisibility(nsIBox* aScrollbar, PRBool aVisible);
/**
@ -186,17 +173,30 @@ public:
* directions of overflow should be reachable by scrolling and which
* should not. Callers should NOT depend on it having any particular
* behavior (although nsXULScrollFrame currently does).
*
* This should only be called when the scrolled frame has been
* reflowed with the scroll port size given in mScrollPort.
*
* Currently it allows scrolling down and to the right for
* nsHTMLScrollFrames with LTR directionality and for all
* nsXULScrollFrames, and allows scrolling down and to the left for
* nsHTMLScrollFrames with RTL directionality.
*/
nsRect GetScrolledRect(const nsSize& aScrollPortSize) const;
nsSize GetScrollPortSize() const
{
return mScrollableView->View()->GetBounds().Size();
}
nsRect GetScrolledRect() const;
/**
* GetScrolledRectInternal is designed to encapsulate deciding which
* directions of overflow should be reachable by scrolling and which
* should not. Callers should NOT depend on it having any particular
* behavior (although nsXULScrollFrame currently does).
*
* Currently it allows scrolling down and to the right for
* nsHTMLScrollFrames with LTR directionality and for all
* nsXULScrollFrames, and allows scrolling down and to the left for
* nsHTMLScrollFrames with RTL directionality.
*/
nsRect GetScrolledRectInternal(const nsRect& aScrolledOverflowArea,
const nsSize& aScrollPortSize) const;
nsMargin GetActualScrollbarSizes() const;
nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState);
@ -204,8 +204,7 @@ public:
PRBool IsScrollbarOnRight() const;
void LayoutScrollbars(nsBoxLayoutState& aState,
const nsRect& aContentArea,
const nsRect& aOldScrollArea,
const nsRect& aScrollArea);
const nsRect& aOldScrollArea);
// owning references to the nsIAnonymousContentCreator-built content
nsCOMPtr<nsIContent> mHScrollbarContent;
@ -214,22 +213,28 @@ public:
nsRevocableEventPtr<ScrollEvent> mScrollEvent;
nsRevocableEventPtr<AsyncScrollPortEvent> mAsyncScrollPortEvent;
nsIScrollableView* mScrollableView;
nsIBox* mHScrollbarBox;
nsIBox* mVScrollbarBox;
nsIFrame* mScrolledFrame;
nsIBox* mScrollCornerBox;
nsContainerFrame* mOuter;
AsyncScroll* mAsyncScroll;
nsCOMArray<nsIScrollPositionListener> mListeners;
nsRect mScrollPort;
// Where we're currently scrolling to, if we're scrolling asynchronously.
// If we're not in the middle of an asynchronous scroll then this is
// just the current scroll position. ScrollBy will choose its
// destination based on this value.
nsPoint mDestination;
nsRect mRestoreRect;
nsPoint mRestorePos;
nsPoint mLastPos;
PRPackedBool mNeverHasVerticalScrollbar:1;
PRPackedBool mNeverHasHorizontalScrollbar:1;
PRPackedBool mHasVerticalScrollbar:1;
PRPackedBool mHasHorizontalScrollbar:1;
PRPackedBool mViewInitiatedScroll:1;
PRPackedBool mFrameInitiatedScroll:1;
PRPackedBool mFrameIsUpdatingScrollbar:1;
PRPackedBool mDidHistoryRestore:1;
// Is this the scrollframe for the document's viewport?
PRPackedBool mIsRoot:1;
@ -322,7 +327,8 @@ public:
PRBool aFirstPass);
nsresult ReflowContents(ScrollReflowState* aState,
const nsHTMLReflowMetrics& aDesiredSize);
void PlaceScrollArea(const ScrollReflowState& aState);
void PlaceScrollArea(const ScrollReflowState& aState,
const nsPoint& aScrollPosition);
nscoord GetIntrinsicVScrollbarWidth(nsIRenderingContext *aRenderingContext);
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
@ -353,10 +359,6 @@ public:
return this;
}
virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
return mInner.GetParentViewForChildFrame(aFrame);
}
virtual nsIFrame* GetContentInsertionFrame() {
return mInner.GetScrolledFrame()->GetContentInsertionFrame();
}
@ -365,7 +367,6 @@ public:
nscoord aX, nscoord aY, nsIFrame* aForChild,
PRUint32 aFlags);
virtual PRBool NeedsView() { return PR_TRUE; }
virtual PRBool DoesClipChildren() { return PR_TRUE; }
virtual nsSplittableType GetSplittableType() const;
@ -479,10 +480,6 @@ protected:
}
PRBool GuessHScrollbarNeeded(const ScrollReflowState& aState);
PRBool GuessVScrollbarNeeded(const ScrollReflowState& aState);
nsSize GetScrollPortSize() const
{
return mInner.GetScrollPortSize();
}
PRBool IsScrollbarUpdateSuppressed() const {
return mInner.mSupppressScrollbarUpdate;
@ -556,10 +553,6 @@ public:
return this;
}
virtual nsIView* GetParentViewForChildFrame(nsIFrame* aFrame) const {
return mInner.GetParentViewForChildFrame(aFrame);
}
virtual nsIFrame* GetContentInsertionFrame() {
return mInner.GetScrolledFrame()->GetContentInsertionFrame();
}
@ -568,7 +561,6 @@ public:
nscoord aX, nscoord aY, nsIFrame* aForChild,
PRUint32 aFlags);
virtual PRBool NeedsView() { return PR_TRUE; }
virtual PRBool DoesClipChildren() { return PR_TRUE; }
virtual nsSplittableType GetSplittableType() const;
@ -590,7 +582,7 @@ public:
NS_IMETHOD GetPadding(nsMargin& aPadding);
nsresult Layout(nsBoxLayoutState& aState);
void LayoutScrollArea(nsBoxLayoutState& aState, const nsRect& aRect);
void LayoutScrollArea(nsBoxLayoutState& aState, const nsPoint& aScrollPosition);
static PRBool AddRemoveScrollbar(PRBool& aHasScrollbar,
nscoord& aXY,
@ -600,15 +592,14 @@ public:
PRBool aAdd);
PRBool AddRemoveScrollbar(nsBoxLayoutState& aState,
nsRect& aScrollAreaSize,
PRBool aOnTop,
PRBool aHorizontal,
PRBool aAdd);
PRBool AddHorizontalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
PRBool AddVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
void RemoveHorizontalScrollbar(nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnBottom);
void RemoveVerticalScrollbar (nsBoxLayoutState& aState, nsRect& aScrollAreaSize, PRBool aOnRight);
PRBool AddHorizontalScrollbar (nsBoxLayoutState& aState, PRBool aOnBottom);
PRBool AddVerticalScrollbar (nsBoxLayoutState& aState, PRBool aOnRight);
void RemoveHorizontalScrollbar(nsBoxLayoutState& aState, PRBool aOnBottom);
void RemoveVerticalScrollbar (nsBoxLayoutState& aState, PRBool aOnRight);
static void AdjustReflowStateForPrintPreview(nsBoxLayoutState& aState, PRBool& aSetBack);
static void AdjustReflowStateBack(nsBoxLayoutState& aState, PRBool aSetBack);

View File

@ -149,9 +149,8 @@ public:
* content is scrolled all the way in the direction(s) given by aDelta.
* @param aOverflow if non-null, returns the amount that scrolling
* was clamped by in each direction (how far we moved the scroll position
to bring it back into the legal range). This is never negative. This
* is only supported for LINES and DEVICE_PIXELS. The values are in
* device pixels.
* to bring it back into the legal range). This is never negative. The
* values are in device pixels.
*/
virtual void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode,
nsIntPoint* aOverflow = nsnull) = 0;

View File

@ -61,7 +61,7 @@ public:
NS_IMETHOD ScrollPositionWillChange(nscoord aX, nscoord aY) = 0;
// The scrollframe implementation of this method appends a list of widget
// configuration requests to aConfigurations. No other implementor
// should touch it.
// should touch it. No longer gets called!!!
virtual void ViewPositionDidChange(nsTArray<nsIWidget::Configuration>* aConfigurations) = 0;
NS_IMETHOD ScrollPositionDidChange(nscoord aX, nscoord aY) = 0;
};

View File

@ -64,8 +64,8 @@ enum nsViewVisibility {
// IID for the nsIView interface
#define NS_IVIEW_IID \
{ 0x18b5f32a, 0x921a, 0x4772, \
{ 0xa4, 0x3d, 0xf3, 0x04, 0x5c, 0xb9, 0xc2, 0x59 } }
{ 0x4435167c, 0xb627, 0x4073, \
{ 0x9c, 0x92, 0xbc, 0x34, 0x39, 0xd9, 0xf8, 0xd2 } }
// Public view flags are defined in this file
#define NS_VIEW_FLAGS_PUBLIC 0x00FF
@ -168,6 +168,12 @@ public:
"root views should always have explicit position of (0,0)");
return nsPoint(mPosX, mPosY);
}
/**
* Set the position of a view. This does not cause any invalidation. It
* does reposition any widgets in this view or its descendants.
*/
virtual void SetPosition(nscoord aX, nscoord aY) = 0;
/**
* Called to get the dimensions and position of the view's bounds.

View File

@ -420,6 +420,41 @@ public:
*/
NS_IMETHOD SynthesizeMouseMove(PRBool aFromScroll)=0;
/**
* Called to inform the view manager that a view is about to bit-blit.
* @param aView the view that will bit-blit
* @param aScrollAmount how much aView will scroll by
* @return always returns NS_OK
* @note
* This method used to return void, but MSVC 6.0 SP5 (without the
* Processor Pack) and SP6, and the MS eMbedded Visual C++ 4.0 SP4
* (for WINCE) hit an internal compiler error when compiling this
* method:
*
* @par
@verbatim
fatal error C1001: INTERNAL COMPILER ERROR
(compiler file 'E:\8966\vc98\p2\src\P2\main.c', line 494)
@endverbatim
*
* @par
* Making the method return nsresult worked around the internal
* compiler error. See Bugzilla bug 281158. (The WINCE internal
* compiler error was addressed by the patch in bug 291229 comment
* 14 although the bug report did not mention the problem.)
*/
virtual nsresult WillBitBlit(nsIView* aView, const nsRect& aRect,
nsPoint aScrollAmount) = 0;
/**
* Called to inform the view manager that a view has scrolled via a
* bitblit.
* The view manager will invalidate any widgets which may need
* to be rerendered.
* @param aView view to paint
* @param aUpdateRegion ensure that this part of the view is repainted
*/
virtual void UpdateViewAfterScroll(nsIView *aView, const nsRegion& aUpdateRegion) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIViewManager, NS_IVIEWMANAGER_IID)

View File

@ -47,8 +47,8 @@ class nsIRenderingContext;
class nsGUIEvent;
#define NS_IVIEWOBSERVER_IID \
{ 0xc85d474d, 0x316e, 0x491c, \
{ 0x8b, 0xc5, 0x24, 0xba, 0xb7, 0xbb, 0x68, 0x9e } }
{ 0xba1357b6, 0xe3c7, 0x426a, \
{ 0xb3, 0x68, 0xfe, 0xe8, 0x24, 0x8c, 0x08, 0x38 } }
class nsIViewObserver : public nsISupports
{
@ -90,16 +90,6 @@ public:
nsIRenderingContext* aRenderingContext,
const nsRect& aDirtyRect) = 0;
/**
* @see nsLayoutUtils::ComputeRepaintRegionForCopy
*/
NS_IMETHOD ComputeRepaintRegionForCopy(nsIView* aRootView,
nsIView* aMovingView,
nsPoint aDelta,
const nsRect& aUpdateRect,
nsRegion* aBlitRegion,
nsRegion* aRepaintRegion) = 0;
/* called when the observer needs to handle an event
* @param aView - where to start processing the event; the root view,
* or the view that's currently capturing this sort of event; must be a view
@ -136,20 +126,6 @@ public:
*/
NS_IMETHOD_(void) WillPaint() = 0;
/**
* Notify the observer that it should invalidate the frame bounds for
* the frame associated with this view, due to scrolling.
*/
NS_IMETHOD_(void) InvalidateFrameForScrolledView(nsIView *aView) = 0;
/**
* Notify the observer that some areas of the root view have been
* invalidated/blitted due to scrolling. A bitblit-scroll occurred
* so we can be sure that rootView->NeedsInvalidateFrameOnScroll is false.
*/
NS_IMETHOD_(void) NotifyInvalidateForScrolledView(const nsRegion& aBlitRegion,
const nsRegion& aInvalidateRegion) = 0;
/**
* Dispatch the given synthesized mouse move event, and if
* aFlushOnHoverChange is true, flush layout if :hover changes cause

View File

@ -54,7 +54,6 @@ EXTRA_DSO_LIBS = gkgfx
CPPSRCS = \
nsView.cpp \
nsScrollPortView.cpp \
nsViewManager.cpp \
$(NULL)

View File

@ -136,6 +136,8 @@ public:
}
nsRegion* GetDirtyRegion() {
if (!mDirtyRegion) {
NS_ASSERTION(!mParent || GetFloating(),
"Only display roots should have dirty regions");
mDirtyRegion = new nsRegion();
NS_ASSERTION(mDirtyRegion, "Out of memory!");
}

View File

@ -581,66 +581,42 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, PRUint32 aUpdateFlags)
return UpdateView(view, bounds, aUpdateFlags);
}
// This method accumulates the intersectons of all dirty regions attached to
// descendants of aSourceView with the cliprect of aTargetView into the dirty
// region of aTargetView, after offseting said intersections by aOffset.
static void
AccumulateIntersectionsIntoDirtyRegion(nsView* aTargetView,
nsView* aSourceView,
const nsPoint& aOffset)
{
if (aSourceView->HasNonEmptyDirtyRegion()) {
// In most cases, aSourceView is an ancestor of aTargetView, since most
// commonly we have dirty rects on the root view.
nsPoint offset = aTargetView->GetOffsetTo(aSourceView);
nsRegion intersection;
intersection = *aSourceView->GetDirtyRegion();
if (!intersection.IsEmpty()) {
nsRegion* targetRegion = aTargetView->GetDirtyRegion();
if (targetRegion) {
intersection.MoveBy(-offset + aOffset);
targetRegion->Or(*targetRegion, intersection);
// Random simplification number...
targetRegion->SimplifyOutward(20);
}
}
}
if (aSourceView == aTargetView) {
// No need to do this with kids of aTargetView
return;
}
for (nsView* kid = aSourceView->GetFirstChild();
kid;
kid = kid->GetNextSibling()) {
AccumulateIntersectionsIntoDirtyRegion(aTargetView, kid, aOffset);
}
}
nsresult
nsViewManager::WillBitBlit(nsView* aView, nsPoint aScrollAmount)
nsViewManager::WillBitBlit(nsIView* aView, const nsRect& aRect,
nsPoint aCopyDelta)
{
if (!IsRootVM()) {
RootViewManager()->WillBitBlit(aView, aScrollAmount);
RootViewManager()->WillBitBlit(aView, aRect, aCopyDelta);
return NS_OK;
}
NS_PRECONDITION(aView, "Must have a view");
NS_PRECONDITION(!aView->NeedsInvalidateFrameOnScroll(), "We shouldn't be BitBlting.");
// aView must be a display root
NS_PRECONDITION(aView &&
(aView == mRootView || aView->GetFloating()),
"Must have a display root view");
++mScrollCnt;
nsView* v = static_cast<nsView*>(aView);
// Since the view is actually moving the widget by -aScrollAmount, that's the
// offset we want to use when accumulating dirty rects.
AccumulateIntersectionsIntoDirtyRegion(aView, GetRootView(), -aScrollAmount);
if (v->HasNonEmptyDirtyRegion()) {
nsRegion* dirty = v->GetDirtyRegion();
nsRegion intersection;
intersection.And(*dirty, aRect);
if (!intersection.IsEmpty()) {
dirty->Or(*dirty, intersection);
// Random simplification number...
dirty->SimplifyOutward(20);
}
}
return NS_OK;
}
// Invalidate all widgets which overlap the view, other than the view's own widgets.
void
nsViewManager::UpdateViewAfterScroll(nsView *aView,
const nsRegion& aBlitRegion,
nsViewManager::UpdateViewAfterScroll(nsIView *aView,
const nsRegion& aUpdateRegion)
{
NS_ASSERTION(RootViewManager()->mScrollCnt > 0,
@ -648,8 +624,9 @@ nsViewManager::UpdateViewAfterScroll(nsView *aView,
// No need to check for empty aUpdateRegion here. We'd still need to
// do most of the work here anyway.
nsView* displayRoot = GetDisplayRootFor(aView);
nsPoint offset = aView->GetOffsetTo(displayRoot);
nsView* view = static_cast<nsView*>(aView);
nsView* displayRoot = GetDisplayRootFor(view);
nsPoint offset = view->GetOffsetTo(displayRoot);
nsRegion update(aUpdateRegion);
update.MoveBy(offset);
@ -657,16 +634,6 @@ nsViewManager::UpdateViewAfterScroll(nsView *aView,
update, nsnull);
// FlushPendingInvalidates();
// Don't send invalidation notifications when we're scrolling in a popup
if (displayRoot == RootViewManager()->mRootView) {
nsPoint rootOffset = aView->GetOffsetTo(mRootView);
nsRegion blit(aBlitRegion);
blit.MoveBy(rootOffset);
update.MoveBy(rootOffset - offset);
GetViewObserver()->NotifyInvalidateForScrolledView(blit, update);
}
Composite();
--RootViewManager()->mScrollCnt;
}
@ -1462,44 +1429,6 @@ NS_IMETHODIMP nsViewManager::ResizeView(nsIView *aView, const nsRect &aRect, PRB
return NS_OK;
}
void nsViewManager::GetRegionsForBlit(nsView* aView, nsPoint aDelta,
nsRegion* aBlitRegion,
nsRegion* aRepaintRegion)
{
NS_ASSERTION(!IsPainting(),
"View manager shouldn't be scrolling during a paint");
nsView* displayRoot = GetDisplayRootFor(aView);
nsPoint displayOffset = aView->GetParent()->GetOffsetTo(displayRoot);
nsRect parentBounds = aView->GetParent()->GetDimensions() + displayOffset;
// The area clipped by the scrolling view is snapped to device pixels
// (in nsThebesRenderingContext::SetClipRect), so snap the bound here
// that we use to compute the blit and repaint regions
PRInt32 p2a = mContext->AppUnitsPerDevPixel();
parentBounds = parentBounds.ToNearestPixels(p2a).ToAppUnits(p2a);
if (IsPainting() || !mObserver) {
// Be simple and safe
aBlitRegion->SetEmpty();
*aRepaintRegion = parentBounds;
} else {
nsresult rv =
mObserver->ComputeRepaintRegionForCopy(displayRoot, aView, -aDelta,
parentBounds,
aBlitRegion,
aRepaintRegion);
if (NS_FAILED(rv)) {
aBlitRegion->SetEmpty();
*aRepaintRegion = nsRegion(parentBounds);
return;
}
}
aBlitRegion->MoveBy(-displayOffset);
aRepaintRegion->MoveBy(-displayOffset);
}
NS_IMETHODIMP nsViewManager::SetViewFloating(nsIView *aView, PRBool aFloating)
{
nsView* view = static_cast<nsView*>(aView);

View File

@ -273,52 +273,10 @@ public: // NOT in nsIViewManager, so private to the view module
nsEventStatus HandleEvent(nsView* aView, nsPoint aPoint, nsGUIEvent* aEvent);
/**
* Called to inform the view manager that a view is about to bit-blit.
* @param aView the view that will bit-blit
* @param aScrollAmount how much aView will scroll by
* @return always returns NS_OK
* @note
* This method used to return void, but MSVC 6.0 SP5 (without the
* Processor Pack) and SP6, and the MS eMbedded Visual C++ 4.0 SP4
* (for WINCE) hit an internal compiler error when compiling this
* method:
*
* @par
@verbatim
fatal error C1001: INTERNAL COMPILER ERROR
(compiler file 'E:\8966\vc98\p2\src\P2\main.c', line 494)
@endverbatim
*
* @par
* Making the method return nsresult worked around the internal
* compiler error. See Bugzilla bug 281158. (The WINCE internal
* compiler error was addressed by the patch in bug 291229 comment
* 14 although the bug report did not mention the problem.)
*/
nsresult WillBitBlit(nsView* aView, nsPoint aScrollAmount);
/**
* Called to inform the view manager that a view has scrolled via a
* bitblit.
* The view manager will invalidate any widgets which may need
* to be rerendered.
* @param aView view to paint. should be the nsScrollPortView that
* got scrolled.
* @param aBlitRegion the region that was blitted; this is just so
* we can notify our view observer
* @param aUpdateRegion ensure that this part of the view is repainted
*/
void UpdateViewAfterScroll(nsView *aView, const nsRegion& aBlitRegion,
const nsRegion& aUpdateRegion);
/**
* Given that the view aView has being moved by scrolling by aDelta
* (so we want to blit pixels by -aDelta), compute the regions that
* must be blitted and repainted to correctly update the screen.
*/
void GetRegionsForBlit(nsView* aView, nsPoint aDelta,
nsRegion* aBlitRegion, nsRegion* aRepaintRegion);
virtual nsresult WillBitBlit(nsIView* aView, const nsRect& aRect,
nsPoint aScrollAmount);
virtual void UpdateViewAfterScroll(nsIView *aView,
const nsRegion& aUpdateRegion);
nsresult CreateRegion(nsIRegion* *result);