зеркало из https://github.com/mozilla/pjs.git
Push view update batching up to the root view manager. Make all associated
members only be accessed by the root view manager. Document the invalidation setup a bit. Bug 244290, r+sr=roc
This commit is contained in:
Родитель
c244a86e0f
Коммит
f958ca676d
|
@ -112,6 +112,11 @@ public:
|
|||
/**
|
||||
* Called to force a redrawing of any dirty areas.
|
||||
*/
|
||||
// XXXbz why is this exposed? Shouldn't update view batches handle this?
|
||||
// It's not like Composite() does what's expected inside a view update batch
|
||||
// anyway, since dirty areas may not have been invalidated on the widget yet
|
||||
// and widget changes may not have been propagated yet. Maybe this should
|
||||
// call FlushPendingInvalidates()?
|
||||
NS_IMETHOD Composite(void) = 0;
|
||||
|
||||
/**
|
||||
|
@ -348,6 +353,9 @@ public:
|
|||
* prevent the view manager from refreshing.
|
||||
* @return error status
|
||||
*/
|
||||
// XXXbz callers of this function don't seem to realize that it disables
|
||||
// refresh for the entire view manager hierarchy.... Maybe it shouldn't do
|
||||
// that?
|
||||
NS_IMETHOD DisableRefresh(void) = 0;
|
||||
|
||||
/**
|
||||
|
@ -409,6 +417,7 @@ public:
|
|||
/**
|
||||
* Display the specified view. Used when printing.
|
||||
*/
|
||||
//XXXbz how is this different from UpdateView(NS_VMREFRESH_IMMEDIATE)?
|
||||
NS_IMETHOD Display(nsIView *aView, nscoord aX, nscoord aY, const nsRect& aClipRect) = 0;
|
||||
|
||||
/**
|
||||
|
@ -437,6 +446,9 @@ public:
|
|||
* Callers should use UpdateView(view, NS_VMREFRESH_IMMEDIATE) in most cases instead
|
||||
* @result error status
|
||||
*/
|
||||
// XXXbz Callers seem to be confused about this one... and it doesn't play
|
||||
// right with view update batching at all (will miss updates). Maybe this
|
||||
// should call FlushPendingInvalidates()?
|
||||
NS_IMETHOD ForceUpdate() = 0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -181,6 +181,7 @@ nsView::nsView()
|
|||
mOpacity = 1.0f;
|
||||
mViewManager = nsnull;
|
||||
mChildRemoved = PR_FALSE;
|
||||
mDirtyRegion = nsnull;
|
||||
}
|
||||
|
||||
void nsView::DropMouseGrabbing() {
|
||||
|
|
|
@ -433,6 +433,8 @@ static PRBool IsViewVisible(nsView *aView)
|
|||
void
|
||||
nsViewManager::PostInvalidateEvent()
|
||||
{
|
||||
NS_ASSERTION(IsRootVM(), "Caller screwed up");
|
||||
|
||||
nsCOMPtr<nsIEventQueue> eventQueue;
|
||||
mEventQueueService->GetSpecialEventQueue(
|
||||
nsIEventQueueService::UI_THREAD_EVENT_QUEUE, getter_AddRefs(eventQueue));
|
||||
|
@ -491,11 +493,14 @@ nsViewManager::~nsViewManager()
|
|||
mRootView = nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEventQueue> eventQueue;
|
||||
mEventQueueService->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE,
|
||||
getter_AddRefs(eventQueue));
|
||||
NS_ASSERTION(nsnull != eventQueue, "Event queue is null");
|
||||
eventQueue->RevokeEvents(this);
|
||||
if (IsRootVM()) {
|
||||
nsCOMPtr<nsIEventQueue> eventQueue;
|
||||
mEventQueueService->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE,
|
||||
getter_AddRefs(eventQueue));
|
||||
NS_ASSERTION(nsnull != eventQueue, "Event queue is null");
|
||||
eventQueue->RevokeEvents(this);
|
||||
}
|
||||
|
||||
mInvalidateEventQueue = nsnull;
|
||||
mSynthMouseMoveEventQueue = nsnull;
|
||||
|
||||
|
@ -615,9 +620,15 @@ NS_IMETHODIMP nsViewManager::SetRootView(nsIView *aView)
|
|||
nsView* parent = mRootView->GetParent();
|
||||
if (parent) {
|
||||
parent->InsertChild(mRootView, nsnull);
|
||||
mRootViewManager = parent->GetViewManager()->RootViewManager();
|
||||
} else {
|
||||
mRootViewManager = this;
|
||||
}
|
||||
|
||||
mRootView->SetZIndex(PR_FALSE, 0, PR_FALSE);
|
||||
} else {
|
||||
// XXXbz not really needed, probably
|
||||
mRootViewManager = this;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -727,7 +738,7 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext,
|
|||
{
|
||||
NS_ASSERTION(aRegion != nsnull, "Null aRegion");
|
||||
|
||||
if (PR_FALSE == mRefreshEnabled)
|
||||
if (! IsRefreshEnabled())
|
||||
return;
|
||||
|
||||
nsRect viewRect;
|
||||
|
@ -760,12 +771,12 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext,
|
|||
MOZ_TIMER_START(mWatch);
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(!mPainting, "recursive painting not permitted");
|
||||
if (mPainting) {
|
||||
mRecursiveRefreshPending = PR_TRUE;
|
||||
NS_ASSERTION(!IsPainting(), "recursive painting not permitted");
|
||||
if (IsPainting()) {
|
||||
RootViewManager()->mRecursiveRefreshPending = PR_TRUE;
|
||||
return;
|
||||
}
|
||||
mPainting = PR_TRUE;
|
||||
SetPainting(PR_TRUE);
|
||||
|
||||
// force double buffering in general
|
||||
aUpdateFlags |= NS_VMREFRESH_DOUBLE_BUFFER;
|
||||
|
@ -795,7 +806,7 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext,
|
|||
|
||||
//couldn't get rendering context. this is ok at init time atleast
|
||||
if (nsnull == localcx) {
|
||||
mPainting = PR_FALSE;
|
||||
SetPainting(PR_FALSE);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -914,7 +925,7 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext,
|
|||
localcx->Translate(viewRect.x, viewRect.y);
|
||||
}
|
||||
|
||||
mPainting = PR_FALSE;
|
||||
SetPainting(PR_FALSE);
|
||||
|
||||
// notify the listeners.
|
||||
if (nsnull != mCompositeListeners) {
|
||||
|
@ -929,9 +940,9 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext,
|
|||
}
|
||||
}
|
||||
|
||||
if (mRecursiveRefreshPending) {
|
||||
if (RootViewManager()->mRecursiveRefreshPending) {
|
||||
UpdateAllViews(aUpdateFlags);
|
||||
mRecursiveRefreshPending = PR_FALSE;
|
||||
RootViewManager()->mRecursiveRefreshPending = PR_FALSE;
|
||||
}
|
||||
|
||||
localcx->ReleaseBackbuffer();
|
||||
|
@ -1544,6 +1555,8 @@ nsViewManager::CreateBlendingBuffers(nsIRenderingContext *aRC,
|
|||
|
||||
void nsViewManager::ProcessPendingUpdates(nsView* aView)
|
||||
{
|
||||
NS_ASSERTION(IsRootVM(), "Updates will be missed");
|
||||
|
||||
// Protect against a null-view.
|
||||
if (!aView) {
|
||||
return;
|
||||
|
@ -1563,18 +1576,20 @@ void nsViewManager::ProcessPendingUpdates(nsView* aView)
|
|||
// process pending updates in child view.
|
||||
for (nsView* childView = aView->GetFirstChild(); childView;
|
||||
childView = childView->GetNextSibling()) {
|
||||
if (childView->GetViewManager() == this) {
|
||||
ProcessPendingUpdates(childView);
|
||||
}
|
||||
ProcessPendingUpdates(childView);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsViewManager::Composite()
|
||||
{
|
||||
if (mUpdateCnt > 0)
|
||||
if (!IsRootVM()) {
|
||||
return RootViewManager()->Composite();
|
||||
}
|
||||
|
||||
if (UpdateCount() > 0)
|
||||
{
|
||||
ForceUpdate();
|
||||
mUpdateCnt = 0;
|
||||
ClearUpdateCount();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1611,12 +1626,7 @@ nsViewManager::UpdateViewAfterScroll(nsIView *aView, PRInt32 aDX, PRInt32 aDY)
|
|||
return;
|
||||
}
|
||||
|
||||
nsView* realRoot = mRootView;
|
||||
while (realRoot->GetParent()) {
|
||||
realRoot = realRoot->GetParent();
|
||||
}
|
||||
|
||||
UpdateWidgetArea(realRoot, damageRect, view);
|
||||
UpdateWidgetArea(RootViewManager()->GetRootView(), damageRect, view);
|
||||
|
||||
Composite();
|
||||
}
|
||||
|
@ -1688,12 +1698,13 @@ PRBool nsViewManager::UpdateWidgetArea(nsView *aWidgetView, const nsRect &aDamag
|
|||
|
||||
if (!childCovers) {
|
||||
nsViewManager* vm = aWidgetView->GetViewManager();
|
||||
++vm->mUpdateCnt;
|
||||
nsViewManager* rootVM = RootViewManager();
|
||||
rootVM->IncrementUpdateCount();
|
||||
|
||||
if (!vm->mRefreshEnabled) {
|
||||
if (!IsRefreshEnabled()) {
|
||||
// accumulate this rectangle in the view's dirty region, so we can process it later.
|
||||
vm->AddRectToDirtyRegion(aWidgetView, bounds);
|
||||
vm->mHasPendingInvalidates = PR_TRUE;
|
||||
rootVM->mHasPendingInvalidates = PR_TRUE;
|
||||
} else {
|
||||
ViewToWidget(aWidgetView, aWidgetView, bounds);
|
||||
widget->Invalidate(bounds, PR_FALSE);
|
||||
|
@ -1743,19 +1754,18 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRU
|
|||
|
||||
UpdateWidgetArea(widgetParent, damagedRect, nsnull);
|
||||
} else {
|
||||
// Propagate the update to the root widget of the root view manager, since
|
||||
// iframes, for example, can overlap each other and be translucent. So we
|
||||
// have to possibly invalidate our rect in each of the widgets we have
|
||||
// lying about.
|
||||
damagedRect.MoveBy(ComputeViewOffset(view));
|
||||
|
||||
nsView* realRoot = mRootView;
|
||||
while (realRoot->GetParent()) {
|
||||
realRoot = realRoot->GetParent();
|
||||
}
|
||||
|
||||
UpdateWidgetArea(realRoot, damagedRect, nsnull);
|
||||
UpdateWidgetArea(RootViewManager()->GetRootView(), damagedRect, nsnull);
|
||||
}
|
||||
|
||||
++mUpdateCnt;
|
||||
RootViewManager()->IncrementUpdateCount();
|
||||
|
||||
if (!mRefreshEnabled) {
|
||||
if (!IsRefreshEnabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1769,6 +1779,10 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRU
|
|||
|
||||
NS_IMETHODIMP nsViewManager::UpdateAllViews(PRUint32 aUpdateFlags)
|
||||
{
|
||||
if (RootViewManager() != this) {
|
||||
return RootViewManager()->UpdateAllViews(aUpdateFlags);
|
||||
}
|
||||
|
||||
UpdateViews(mRootView, aUpdateFlags);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1781,9 +1795,7 @@ void nsViewManager::UpdateViews(nsView *aView, PRUint32 aUpdateFlags)
|
|||
// update all children as well.
|
||||
nsView* childView = aView->GetFirstChild();
|
||||
while (nsnull != childView) {
|
||||
if (childView->GetViewManager() == this) {
|
||||
UpdateViews(childView, aUpdateFlags);
|
||||
}
|
||||
UpdateViews(childView, aUpdateFlags);
|
||||
childView = childView->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
@ -1854,7 +1866,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS
|
|||
break;
|
||||
|
||||
// Refresh the view
|
||||
if (mRefreshEnabled) {
|
||||
if (IsRefreshEnabled()) {
|
||||
// If an ancestor widget was hidden and then shown, we could
|
||||
// have a delayed resize to handle.
|
||||
if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
|
||||
|
@ -2239,8 +2251,9 @@ void nsViewManager::BuildDisplayList(nsView* aView, const nsRect& aRect, PRBool
|
|||
void nsViewManager::BuildEventTargetList(nsVoidArray &aTargets, nsView* aView, nsGUIEvent* aEvent,
|
||||
PRBool aCaptured, PLArenaPool &aPool)
|
||||
{
|
||||
NS_ASSERTION(!mPainting, "View manager cannot handle events during a paint");
|
||||
if (mPainting) {
|
||||
NS_ASSERTION(!IsPainting(),
|
||||
"View manager cannot handle events during a paint");
|
||||
if (IsPainting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2363,9 +2376,8 @@ nsEventStatus nsViewManager::HandleEvent(nsView* aView, nsGUIEvent* aEvent, PRBo
|
|||
|
||||
NS_IMETHODIMP nsViewManager::GrabMouseEvents(nsIView *aView, PRBool &aResult)
|
||||
{
|
||||
nsView* rootParent = mRootView ? mRootView->GetParent() : nsnull;
|
||||
if (rootParent) {
|
||||
return rootParent->GetViewManager()->GrabMouseEvents(aView, aResult);
|
||||
if (!IsRootVM()) {
|
||||
return RootViewManager()->GrabMouseEvents(aView, aResult);
|
||||
}
|
||||
|
||||
// Along with nsView::SetVisibility, we enforce that the mouse grabber
|
||||
|
@ -2395,20 +2407,6 @@ NS_IMETHODIMP nsViewManager::GrabKeyEvents(nsIView *aView, PRBool &aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsView* nsViewManager::GetMouseEventGrabber() const {
|
||||
nsView* root = mRootView;
|
||||
while (root && root->GetParent()) {
|
||||
nsViewManager* viewManager = root->GetParent()->GetViewManager();
|
||||
if (!viewManager)
|
||||
return nsnull;
|
||||
root = viewManager->mRootView;
|
||||
}
|
||||
if (!root)
|
||||
return nsnull;
|
||||
nsViewManager* viewManager = root->GetViewManager();
|
||||
return viewManager ? viewManager->mMouseGrabber : nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsViewManager::GetMouseEventGrabber(nsIView *&aView)
|
||||
{
|
||||
aView = GetMouseEventGrabber();
|
||||
|
@ -2827,8 +2825,9 @@ static PRBool IsAncestorOf(const nsView* aAncestor, const nsView* aView)
|
|||
*/
|
||||
PRBool nsViewManager::CanScrollWithBitBlt(nsView* aView)
|
||||
{
|
||||
NS_ASSERTION(!mPainting, "View manager shouldn't be scrolling during a paint");
|
||||
if (mPainting) {
|
||||
NS_ASSERTION(!IsPainting(),
|
||||
"View manager shouldn't be scrolling during a paint");
|
||||
if (IsPainting()) {
|
||||
return PR_FALSE; // do the safe thing
|
||||
}
|
||||
|
||||
|
@ -2999,6 +2998,21 @@ NS_IMETHODIMP nsViewManager::SetViewVisibility(nsIView *aView, nsViewVisibility
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsViewManager::UpdateWidgetsForView(nsView* aView)
|
||||
{
|
||||
NS_PRECONDITION(aView, "Must have view!");
|
||||
|
||||
if (aView->HasWidget()) {
|
||||
aView->GetWidget()->Update();
|
||||
}
|
||||
|
||||
for (nsView* childView = aView->GetFirstChild();
|
||||
childView;
|
||||
childView = childView->GetNextSibling()) {
|
||||
UpdateWidgetsForView(childView);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool nsViewManager::IsViewInserted(nsView *aView)
|
||||
{
|
||||
if (mRootView == aView) {
|
||||
|
@ -3213,6 +3227,10 @@ void nsViewManager::AddRectToDirtyRegion(nsView* aView, const nsRect &aRect) con
|
|||
|
||||
NS_IMETHODIMP nsViewManager::DisableRefresh(void)
|
||||
{
|
||||
if (!IsRootVM()) {
|
||||
return RootViewManager()->DisableRefresh();
|
||||
}
|
||||
|
||||
if (mUpdateBatchCnt > 0)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -3222,6 +3240,10 @@ NS_IMETHODIMP nsViewManager::DisableRefresh(void)
|
|||
|
||||
NS_IMETHODIMP nsViewManager::EnableRefresh(PRUint32 aUpdateFlags)
|
||||
{
|
||||
if (!IsRootVM()) {
|
||||
return RootViewManager()->EnableRefresh(aUpdateFlags);
|
||||
}
|
||||
|
||||
if (mUpdateBatchCnt > 0)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -3245,6 +3267,10 @@ NS_IMETHODIMP nsViewManager::EnableRefresh(PRUint32 aUpdateFlags)
|
|||
|
||||
NS_IMETHODIMP nsViewManager::BeginUpdateViewBatch(void)
|
||||
{
|
||||
if (!IsRootVM()) {
|
||||
return RootViewManager()->BeginUpdateViewBatch();
|
||||
}
|
||||
|
||||
nsresult result = NS_OK;
|
||||
|
||||
if (mUpdateBatchCnt == 0) {
|
||||
|
@ -3260,6 +3286,10 @@ NS_IMETHODIMP nsViewManager::BeginUpdateViewBatch(void)
|
|||
|
||||
NS_IMETHODIMP nsViewManager::EndUpdateViewBatch(PRUint32 aUpdateFlags)
|
||||
{
|
||||
if (!IsRootVM()) {
|
||||
return RootViewManager()->EndUpdateViewBatch(aUpdateFlags);
|
||||
}
|
||||
|
||||
nsresult result = NS_OK;
|
||||
|
||||
--mUpdateBatchCnt;
|
||||
|
@ -3305,19 +3335,19 @@ NS_IMETHODIMP nsViewManager::Display(nsIView* aView, nscoord aX, nscoord aY, con
|
|||
nsView *view = NS_STATIC_CAST(nsView*, aView);
|
||||
nsIRenderingContext *localcx = nsnull;
|
||||
|
||||
if (PR_FALSE == mRefreshEnabled)
|
||||
if (! IsRefreshEnabled())
|
||||
return NS_OK;
|
||||
|
||||
NS_ASSERTION(!(PR_TRUE == mPainting), "recursive painting not permitted");
|
||||
NS_ASSERTION(!IsPainting(), "recursive painting not permitted");
|
||||
|
||||
mPainting = PR_TRUE;
|
||||
SetPainting(PR_TRUE);
|
||||
|
||||
mContext->CreateRenderingContext(localcx);
|
||||
|
||||
//couldn't get rendering context. this is ok if at startup
|
||||
if (nsnull == localcx)
|
||||
{
|
||||
mPainting = PR_FALSE;
|
||||
SetPainting(PR_FALSE);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -3340,7 +3370,7 @@ NS_IMETHODIMP nsViewManager::Display(nsIView* aView, nscoord aX, nscoord aY, con
|
|||
|
||||
NS_RELEASE(localcx);
|
||||
|
||||
mPainting = PR_FALSE;
|
||||
SetPainting(PR_FALSE);
|
||||
|
||||
return NS_OK;
|
||||
|
||||
|
@ -3373,9 +3403,12 @@ NS_IMETHODIMP nsViewManager::GetWidget(nsIWidget **aWidget)
|
|||
|
||||
NS_IMETHODIMP nsViewManager::ForceUpdate()
|
||||
{
|
||||
nsIWidget* widget = GetWidget();
|
||||
if (widget)
|
||||
widget->Update();
|
||||
if (!IsRootVM()) {
|
||||
return RootViewManager()->ForceUpdate();
|
||||
}
|
||||
|
||||
// Walk the view tree looking for widgets, and call Update() on each one
|
||||
UpdateWidgetsForView(mRootView);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3881,11 +3914,24 @@ void nsViewManager::ShowDisplayList(const nsVoidArray* aDisplayList)
|
|||
|
||||
nsPoint nsViewManager::ComputeViewOffset(const nsView *aView)
|
||||
{
|
||||
NS_PRECONDITION(aView, "Null view in ComputeViewOffset?");
|
||||
|
||||
nsPoint origin(0, 0);
|
||||
#ifdef DEBUG
|
||||
const nsView* rootView;
|
||||
const nsView* origView = aView;
|
||||
#endif
|
||||
|
||||
while (aView) {
|
||||
#ifdef DEBUG
|
||||
rootView = aView;
|
||||
#endif
|
||||
origin += aView->GetPosition();
|
||||
aView = aView->GetParent();
|
||||
}
|
||||
NS_ASSERTION(rootView ==
|
||||
origView->GetViewManager()->RootViewManager()->GetRootView(),
|
||||
"Unexpected root view");
|
||||
return origin;
|
||||
}
|
||||
|
||||
|
@ -3896,6 +3942,7 @@ PRBool nsViewManager::DoesViewHaveNativeWidget(nsView* aView)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsView* nsViewManager::GetWidgetView(nsView *aView)
|
||||
{
|
||||
while (aView) {
|
||||
|
@ -4053,13 +4100,17 @@ nsViewManager::AllowDoubleBuffering(PRBool aDoubleBuffer)
|
|||
NS_IMETHODIMP
|
||||
nsViewManager::IsPainting(PRBool& aIsPainting)
|
||||
{
|
||||
aIsPainting = mPainting;
|
||||
aIsPainting = IsPainting();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsViewManager::FlushPendingInvalidates()
|
||||
{
|
||||
if (!IsRootVM()) {
|
||||
return RootViewManager()->FlushPendingInvalidates();
|
||||
}
|
||||
|
||||
if (mHasPendingInvalidates) {
|
||||
ProcessPendingUpdates(mRootView);
|
||||
mHasPendingInvalidates = PR_FALSE;
|
||||
|
@ -4070,6 +4121,8 @@ nsViewManager::FlushPendingInvalidates()
|
|||
void
|
||||
nsViewManager::ProcessInvalidateEvent()
|
||||
{
|
||||
NS_ASSERTION(IsRootVM(),
|
||||
"Incorrectly targeted invalidate event");
|
||||
FlushPendingInvalidates();
|
||||
mInvalidateEventQueue = nsnull;
|
||||
}
|
||||
|
|
|
@ -92,6 +92,37 @@ class nsHashtable;
|
|||
fixed-position frames.
|
||||
*/
|
||||
|
||||
/**
|
||||
Invalidation model:
|
||||
|
||||
1) Callers call into the view manager and ask it to update a view.
|
||||
|
||||
2) The view manager finds the "right" widget for the view, henceforth called
|
||||
the root widget.
|
||||
|
||||
3) The view manager traverses descendants of the root widget and for each
|
||||
one that needs invalidation either
|
||||
|
||||
a) Calls Invalidate() on the widget (no batching)
|
||||
or
|
||||
b) Stores the rect to invalidate on the widget's view (batching)
|
||||
|
||||
// XXXbz we want to change this a bit. See bug 243726
|
||||
|
||||
4) When batching, the call to end the batch either processes the pending
|
||||
Invalidate() calls on the widgets or posts an event to do so.
|
||||
|
||||
It's important to note that widgets associated to views outside this view
|
||||
manager can end up being invalidated during step 3. Therefore, the end of a
|
||||
view update batch really needs to traverse the entire view tree, to ensure
|
||||
that those invalidates happen.
|
||||
|
||||
To cope with this, invalidate event processing and view update batch
|
||||
handling should only happen on the root viewmanager. This means the root
|
||||
view manager is the only thing keeping track of mUpdateCnt. As a result,
|
||||
Composite() calls should also be forwarded to the root view manager.
|
||||
*/
|
||||
|
||||
class nsZPlaceholderView : public nsView
|
||||
{
|
||||
public:
|
||||
|
@ -308,6 +339,12 @@ private:
|
|||
|
||||
PRBool IsViewInserted(nsView *aView);
|
||||
|
||||
/**
|
||||
* Function to recursively call Update() on all widgets belonging to
|
||||
* a view or its kids.
|
||||
*/
|
||||
void UpdateWidgetsForView(nsView* aView);
|
||||
|
||||
/**
|
||||
* Returns the nearest parent view with an attached widget. Can be the
|
||||
* same view as passed-in.
|
||||
|
@ -364,10 +401,47 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// Safety helpers
|
||||
void IncrementUpdateCount() {
|
||||
NS_ASSERTION(IsRootVM(),
|
||||
"IncrementUpdateCount called on non-root viewmanager");
|
||||
++mUpdateCnt;
|
||||
}
|
||||
|
||||
void DecrementUpdateCount() {
|
||||
NS_ASSERTION(IsRootVM(),
|
||||
"DecrementUpdateCount called on non-root viewmanager");
|
||||
--mUpdateCnt;
|
||||
}
|
||||
|
||||
PRInt32 UpdateCount() const {
|
||||
NS_ASSERTION(IsRootVM(),
|
||||
"DecrementUpdateCount called on non-root viewmanager");
|
||||
return mUpdateCnt;
|
||||
}
|
||||
|
||||
void ClearUpdateCount() {
|
||||
NS_ASSERTION(IsRootVM(),
|
||||
"DecrementUpdateCount called on non-root viewmanager");
|
||||
mUpdateCnt = 0;
|
||||
}
|
||||
|
||||
PRBool IsPainting() const {
|
||||
return RootViewManager()->mPainting;
|
||||
}
|
||||
|
||||
void SetPainting(PRBool aPainting) {
|
||||
RootViewManager()->mPainting = aPainting;
|
||||
}
|
||||
|
||||
public: // NOT in nsIViewManager, so private to the view module
|
||||
nsView* GetRootView() const { return mRootView; }
|
||||
nsView* GetMouseEventGrabber() const;
|
||||
nsView* GetMouseEventGrabber() const {
|
||||
return RootViewManager()->mMouseGrabber;
|
||||
}
|
||||
nsView* GetKeyEventGrabber() const { return mKeyGrabber; }
|
||||
nsViewManager* RootViewManager() const { return mRootViewManager; }
|
||||
PRBool IsRootVM() const { return this == RootViewManager(); }
|
||||
|
||||
nsEventStatus HandleEvent(nsView* aView, nsGUIEvent* aEvent, PRBool aCaptured);
|
||||
|
||||
|
@ -389,18 +463,14 @@ public: // NOT in nsIViewManager, so private to the view module
|
|||
// not be in this view manager).
|
||||
static nsPoint ComputeViewOffset(const nsView *aView);
|
||||
|
||||
PRBool IsRefreshEnabled() { return mRefreshEnabled; }
|
||||
PRBool IsRefreshEnabled() { return RootViewManager()->mRefreshEnabled; }
|
||||
|
||||
private:
|
||||
nsIDeviceContext *mContext;
|
||||
float mTwipsToPixels;
|
||||
float mPixelsToTwips;
|
||||
nsIViewObserver *mObserver;
|
||||
nsView *mMouseGrabber;
|
||||
nsView *mKeyGrabber;
|
||||
PRInt32 mUpdateCnt;
|
||||
PRInt32 mUpdateBatchCnt;
|
||||
PRUint32 mUpdateBatchFlags;
|
||||
nsIScrollableView *mRootScrollable;
|
||||
nscolor mDefaultBackgroundColor;
|
||||
nsPoint mMouseLocation; // device units, relative to mRootView
|
||||
|
@ -413,13 +483,28 @@ private:
|
|||
nsISupportsArray *mCompositeListeners;
|
||||
nsCOMPtr<nsIFactory> mRegionFactory;
|
||||
nsView *mRootView;
|
||||
nsViewManager *mRootViewManager;
|
||||
nsCOMPtr<nsIEventQueueService> mEventQueueService;
|
||||
nsCOMPtr<nsIEventQueue> mInvalidateEventQueue;
|
||||
nsCOMPtr<nsIEventQueue> mSynthMouseMoveEventQueue;
|
||||
PRPackedBool mAllowDoubleBuffering;
|
||||
|
||||
// The following members should not be accessed directly except by
|
||||
// the root view manager. Some have accessor functions to enforce
|
||||
// this, as noted.
|
||||
|
||||
// Use GrabMouseEvents() and GetMouseEventGrabber() to access mMouseGrabber.
|
||||
nsView *mMouseGrabber;
|
||||
// Use IncrementUpdateCount(), DecrementUpdateCount(), UpdateCount(),
|
||||
// ClearUpdateCount() on the root viewmanager to access mUpdateCnt.
|
||||
PRInt32 mUpdateCnt;
|
||||
PRInt32 mUpdateBatchCnt;
|
||||
PRUint32 mUpdateBatchFlags;
|
||||
nsCOMPtr<nsIEventQueue> mInvalidateEventQueue;
|
||||
// Use IsRefreshEnabled() to check the value of mRefreshEnabled.
|
||||
PRPackedBool mRefreshEnabled;
|
||||
// Use IsPainting() and SetPainting() to access mPainting.
|
||||
PRPackedBool mPainting;
|
||||
PRPackedBool mRecursiveRefreshPending;
|
||||
PRPackedBool mAllowDoubleBuffering;
|
||||
PRPackedBool mHasPendingInvalidates;
|
||||
|
||||
//from here to public should be static and locked... MMP
|
||||
|
|
|
@ -912,13 +912,6 @@ NS_IMETHODIMP nsWindow::Update(void)
|
|||
// g_print("nsWidget::Update(this=%p): avoided update of empty area\n", this);
|
||||
}
|
||||
|
||||
// The view manager also expects us to force our
|
||||
// children to update too!
|
||||
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
kid->Update();
|
||||
}
|
||||
|
||||
// While I'd think you should NS_RELEASE(aPaintEvent.widget) here,
|
||||
// if you do, it is a NULL pointer. Not sure where it is getting
|
||||
// released.
|
||||
|
|
|
@ -602,13 +602,6 @@ NS_IMETHODIMP nsWindow::Update(void)
|
|||
}
|
||||
}
|
||||
|
||||
// The view manager also expects us to force our
|
||||
// children to update too!
|
||||
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
kid->Update();
|
||||
}
|
||||
|
||||
// While I'd think you should NS_RELEASE(aPaintEvent.widget) here,
|
||||
// if you do, it is a NULL pointer. Not sure where it is getting
|
||||
// released.
|
||||
|
|
Загрузка…
Ссылка в новой задаче