made form elements scroll smoothly. added apis to widgets to support this.

This commit is contained in:
michaelp 1998-05-13 03:39:08 +00:00
Родитель 51dcc96d82
Коммит 936ee3ae67
5 изменённых файлов: 171 добавлений и 20 удалений

Просмотреть файл

@ -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);
}
}
}
}

Просмотреть файл

@ -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);
}
}
}

Просмотреть файл

@ -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__

Просмотреть файл

@ -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));
}
}
}

Просмотреть файл

@ -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(); \
}