diff --git a/mozilla/view/src/nsScrollingView.cpp b/mozilla/view/src/nsScrollingView.cpp index f5e42d270b6..aea898bff99 100644 --- a/mozilla/view/src/nsScrollingView.cpp +++ b/mozilla/view/src/nsScrollingView.cpp @@ -299,7 +299,11 @@ nsEventStatus nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent clip.height = NS_TO_INT_ROUND(scale * (mBounds.height - sy)); mViewManager->ClearDirtyRegion(); - mWindow->Scroll(0, dy, &clip); + + nsIWidget *thiswin = GetWidget(); + + if (nsnull != thiswin) + thiswin->BeginResizingChildren(); //and now we make sure that the scrollbar thumb is in sync with the //numbers we came up with here, but only if we actually moved at least @@ -307,6 +311,18 @@ nsEventStatus nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent //very slow scrolling would never actually work. ((nsScrollbarEvent *)aEvent)->position = mOffsetY; + + if (dy != 0) + { + AdjustChildWidgets(0, dy); + mWindow->Scroll(0, dy, &clip); + } + + if (nsnull != thiswin) + { + thiswin->EndResizingChildren(); + NS_RELEASE(thiswin); + } } } else if ((nsnull != mHScrollBarView) && (scview == mHScrollBarView)) @@ -344,7 +360,11 @@ nsEventStatus nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent clip.height = NS_TO_INT_ROUND(scale * (mBounds.height - sy)); mViewManager->ClearDirtyRegion(); - mWindow->Scroll(dx, 0, &clip); + + nsIWidget *thiswin = GetWidget(); + + if (nsnull != thiswin) + thiswin->BeginResizingChildren(); //and now we make sure that the scrollbar thumb is in sync with the //numbers we came up with here, but only if we actually moved at least @@ -352,12 +372,21 @@ nsEventStatus nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent //very slow scrolling would never actually work. ((nsScrollbarEvent *)aEvent)->position = mOffsetX; + + if (dx != 0) + { + AdjustChildWidgets(dx, 0); + mWindow->Scroll(dx, 0, &clip); + } + + if (nsnull != thiswin) + { + thiswin->EndResizingChildren(); + NS_RELEASE(thiswin); + } } } - if ((dx != 0) || (dy != 0)) - AdjustChildWidgets(dx, dy); - retval = nsEventStatus_eConsumeNoDefault; NS_RELEASE(px); @@ -388,6 +417,7 @@ void nsScrollingView :: ComputeContainerSize() nscoord dx = 0, dy = 0; nsIPresContext *px = mViewManager->GetPresContext(); nscoord width, height; + nscoord vwidth, vheight; PRUint32 oldsizey = mSizeY, oldsizex = mSizeX; nsRect area(0, 0, 0, 0); nscoord offx, offy; @@ -400,7 +430,7 @@ void nsScrollingView :: ComputeContainerSize() if (nsnull != mVScrollBarView) { - mVScrollBarView->GetDimensions(&width, &height); + mVScrollBarView->GetDimensions(&vwidth, &vheight); offy = mOffsetY; win = mVScrollBarView->GetWidget(); @@ -430,7 +460,8 @@ void nsScrollingView :: ComputeContainerSize() mVScrollBarView->SetVisibility(nsViewVisibility_kHide); } - NS_RELEASE(scrollv); + //don't release the vertical scroller here because if we need to + //create a horizontal one, it will need to tweak the vertical one } NS_RELEASE(win); @@ -459,7 +490,13 @@ void nsScrollingView :: ComputeContainerSize() dx = NS_TO_INT_ROUND(scale * (offx - mOffsetX)); - scrollh->SetParameters(mSizeX, mBounds.width, mOffsetX, NS_POINTS_TO_TWIPS_INT(12)); + scrollh->SetParameters(mSizeX, mBounds.width - ((nsnull != scrollv) ? vwidth : 0), + mOffsetX, NS_POINTS_TO_TWIPS_INT(12)); + + //now make the vertical scroll region account for this scrollbar + + if (nsnull != scrollv) + scrollv->SetParameters(mSizeY, mBounds.height - height, mOffsetY, NS_POINTS_TO_TWIPS_INT(12)); } else { @@ -474,6 +511,10 @@ void nsScrollingView :: ComputeContainerSize() NS_RELEASE(win); } + // now we can release the vertical srcoller if there was one... + + NS_IF_RELEASE(scrollv); + if ((dx != 0) || (dy != 0)) AdjustChildWidgets(dx, dy); @@ -537,7 +578,7 @@ void nsScrollingView :: GetVisibleOffset(nscoord *aOffsetX, nscoord *aOffsetY) void nsScrollingView :: AdjustChildWidgets(nscoord aDx, nscoord aDy) { - PRInt32 numkids = GetChildCount(); + PRInt32 numkids = GetChildCount(); for (PRInt32 cnt = 0; cnt < numkids; cnt++) { @@ -551,13 +592,18 @@ void nsScrollingView :: AdjustChildWidgets(nscoord aDx, nscoord aDy) { nsRect bounds; + win->BeginResizingChildren(); win->GetBounds(bounds); win->Move(bounds.x + aDx, bounds.y + aDy); - - NS_RELEASE(win); } kid->AdjustChildWidgets(aDx, aDy); + + if (nsnull != win) + { + win->EndResizingChildren(); + NS_RELEASE(win); + } } } } diff --git a/mozilla/view/src/nsView.cpp b/mozilla/view/src/nsView.cpp index 0cf5a016e10..96a06fce5be 100644 --- a/mozilla/view/src/nsView.cpp +++ b/mozilla/view/src/nsView.cpp @@ -877,12 +877,17 @@ void nsView :: AdjustChildWidgets(nscoord aDx, nscoord aDy) { nsRect bounds; + win->BeginResizingChildren(); win->GetBounds(bounds); win->Move(bounds.x + aDx, bounds.y + aDy); - - NS_RELEASE(win); } kid->AdjustChildWidgets(aDx, aDy); + + if (nsnull != win) + { + win->EndResizingChildren(); + NS_RELEASE(win); + } } } diff --git a/mozilla/widget/public/nsIWidget.h b/mozilla/widget/public/nsIWidget.h index e486e0eda75..bf1c8831d79 100644 --- a/mozilla/widget/public/nsIWidget.h +++ b/mozilla/widget/public/nsIWidget.h @@ -433,6 +433,23 @@ class nsIWidget : public nsISupports { virtual void ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect) = 0; + /** + * When adjustments are to made to a whole set of child widgets, call this + * before resizing/positioning the child windows to minimize repaints. Must + * be followed by EndResizingChildren() after child windows have been + * adjusted. + * + */ + + virtual void BeginResizingChildren(void) = 0; + + /** + * Call this when finished adjusting child windows. Must be preceded by + * BeginResizingChildren(). + * + */ + + virtual void EndResizingChildren(void) = 0; }; #endif // nsIWidget_h__ diff --git a/mozilla/widget/src/windows/nsWindow.cpp b/mozilla/widget/src/windows/nsWindow.cpp index 398a30167b1..d4606cb9238 100644 --- a/mozilla/widget/src/windows/nsWindow.cpp +++ b/mozilla/widget/src/windows/nsWindow.cpp @@ -42,7 +42,27 @@ extern HINSTANCE g_hinst; static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); +//------------------------------------------------------------------------- +// +// Deferred Window positioning +// +//------------------------------------------------------------------------- +void nsWindow::BeginResizingChildren(void) +{ + if (NULL == mDeferredPositioner) + mDeferredPositioner = ::BeginDeferWindowPos(1); +//printf("begin defer on %x, parent %x\n", mWnd, ::GetParent(mWnd)); +} + +void nsWindow::EndResizingChildren(void) +{ + if (NULL != mDeferredPositioner) { +//printf("end defer on %x, parent %x\n", mWnd, ::GetParent(mWnd)); + ::EndDeferWindowPos(mDeferredPositioner); + mDeferredPositioner = NULL; + } +} // DoCreateTooltip - creates a tooltip control and adds some tools // to it. @@ -313,6 +333,7 @@ nsWindow::nsWindow(nsISupports *aOuter) : nsObject(aOuter) mIsAltDown = PR_FALSE; mIsDestroying = PR_FALSE; mTooltip = NULL; + mDeferredPositioner = NULL; } @@ -556,6 +577,11 @@ void nsWindow::Destroy() return; } + //if we were in the middle deferred window positioning + if (mDeferredPositioner) { + VERIFY(::EndDeferWindowPos(mDeferredPositioner)); + } + // destroy the nsWindow if (mWnd) { // destroy the nsWindow @@ -585,7 +611,7 @@ nsIWidget* nsWindow::GetParent(void) if (mWnd) { HWND parent = ::GetParent(mWnd); if (parent) { - nsIWidget* widget = (nsIWidget*)::GetWindowLong(mWnd, GWL_USERDATA); + widget = (nsIWidget*)((nsWindow *)::GetWindowLong(mWnd, GWL_USERDATA)); widget->AddRef(); } } @@ -674,8 +700,23 @@ void nsWindow::Show(PRBool bState) void nsWindow::Move(PRUint32 aX, PRUint32 aY) { if (mWnd) { - VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, 0, 0, - SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE)); + nsIWidget *par = GetParent(); + HDWP deferrer = NULL; + + if (nsnull != par) { + deferrer = ((nsWindow *)par)->mDeferredPositioner; + NS_RELEASE(par); + } + + if (NULL != deferrer) { +//printf("move: deferring\n"); + VERIFY(::DeferWindowPos(deferrer, mWnd, NULL, aX, aY, 0, 0, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE)); + } + else { + VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, 0, 0, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE)); + } } } @@ -687,8 +728,23 @@ void nsWindow::Move(PRUint32 aX, PRUint32 aY) void nsWindow::Resize(PRUint32 aWidth, PRUint32 aHeight) { if (mWnd) { - VERIFY(::SetWindowPos(mWnd, NULL, 0, 0, aWidth, aHeight, - SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE)); + nsIWidget *par = GetParent(); + HDWP deferrer = NULL; + + if (nsnull != par) { + deferrer = ((nsWindow *)par)->mDeferredPositioner; + NS_RELEASE(par); + } + + if (NULL != deferrer) { +//printf("resize: deferring\n"); + VERIFY(::DeferWindowPos(deferrer, mWnd, NULL, 0, 0, aWidth, aHeight, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE)); + } + else { + VERIFY(::SetWindowPos(mWnd, NULL, 0, 0, aWidth, aHeight, + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE)); + } } } @@ -701,8 +757,23 @@ void nsWindow::Resize(PRUint32 aWidth, PRUint32 aHeight) void nsWindow::Resize(PRUint32 aX, PRUint32 aY, PRUint32 aWidth, PRUint32 aHeight) { if (mWnd) { - VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, aWidth, aHeight, - SWP_NOZORDER | SWP_NOACTIVATE)); + nsIWidget *par = GetParent(); + HDWP deferrer = NULL; + + if (nsnull != par) { + deferrer = ((nsWindow *)par)->mDeferredPositioner; + NS_RELEASE(par); + } + + if (NULL != deferrer) { +//printf("resize: deferring\n"); + VERIFY(::DeferWindowPos(deferrer, mWnd, NULL, aX, aY, aWidth, aHeight, + SWP_NOZORDER | SWP_NOACTIVATE)); + } + else { + VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, aWidth, aHeight, + SWP_NOZORDER | SWP_NOACTIVATE)); + } } } diff --git a/mozilla/widget/src/windows/nsWindow.h b/mozilla/widget/src/windows/nsWindow.h index cacd3080b93..56008c3a1f4 100644 --- a/mozilla/widget/src/windows/nsWindow.h +++ b/mozilla/widget/src/windows/nsWindow.h @@ -116,6 +116,8 @@ public: virtual void ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect); virtual void AddMouseListener(nsIMouseListener * aListener); virtual void AddEventListener(nsIEventListener * aListener); + virtual void BeginResizingChildren(void); + virtual void EndResizingChildren(void); // nsSwitchToUIThread interface virtual BOOL CallMethod(MethodInfo *info); @@ -219,6 +221,8 @@ protected: }; static BOOL sIsRegistered; + + HDWP mDeferredPositioner; }; // @@ -409,6 +413,14 @@ protected: void ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect) \ { \ nsWindow::ScreenToWidget(aOldRect, aNewRect); \ + } \ + void BeginResizingChildren(void) \ + { \ + nsWindow::BeginResizingChildren(); \ + } \ + void EndResizingChildren(void) \ + { \ + nsWindow::EndResizingChildren(); \ }