diff --git a/view/public/nsIView.h b/view/public/nsIView.h index 73a446543b7..f972188a42e 100644 --- a/view/public/nsIView.h +++ b/view/public/nsIView.h @@ -360,12 +360,20 @@ public: virtual nsIFrame * GetFrame() = 0; /** - * Move child widgets around by (dx, dy). deltas are in widget - * coordinate space. - * @param aDx x delta - * @param aDy y delta + * Get the nearest widget in this view or a parent of this view and + * the offset from the view that contains the widget to this view + * @param aDx out parameter for x offset + * @param aDy out parameter for y offset + * @return widget (if there is one) closest to view */ - virtual void AdjustChildWidgets(nscoord aDx, nscoord aDy) = 0; + virtual nsIWidget * GetOffsetFromWidget(nscoord *aDx, nscoord *aDy) = 0; + + /** + * Get the visible offset of scrollable view (if any) that contains this view + * @param aDx out parameter for x offset + * @param aDy out parameter for y offset + */ + virtual void GetScrollOffset(nscoord *aDx, nscoord *aDy) = 0; /** * Output debug info to FILE @@ -394,4 +402,9 @@ public: //during event propagation, see if sibling views can handle the event #define NS_VIEW_FLAG_CHECK_SIBLINGS 0x0010 +//passed down through the class hierarchy +//to indicate that the clip is set by an +//outer class +#define NS_VIEW_FLAG_CLIP_SET 0x0020 + #endif diff --git a/view/src/nsScrollingView.cpp b/view/src/nsScrollingView.cpp index bd022c93760..5280e685b61 100644 --- a/view/src/nsScrollingView.cpp +++ b/view/src/nsScrollingView.cpp @@ -53,8 +53,14 @@ void ScrollBarView :: SetPosition(nscoord x, nscoord y) { nsIPresContext *px = mViewManager->GetPresContext(); float scale = px->GetTwipsToPixels(); + nscoord parx = 0, pary = 0; + nsIWidget *pwidget = nsnull; + + pwidget = GetOffsetFromWidget(&parx, &pary); + NS_IF_RELEASE(pwidget); - mWindow->Move(NS_TO_INT_ROUND(x * scale), NS_TO_INT_ROUND(y * scale)); + mWindow->Move(NS_TO_INT_ROUND((x + parx) * scale), + NS_TO_INT_ROUND((y + pary) * scale)); NS_RELEASE(px); } @@ -245,17 +251,52 @@ void nsScrollingView :: SetDimensions(nscoord width, nscoord height) NS_RELEASE(cx); } +void nsScrollingView :: SetPosition(nscoord aX, nscoord aY) +{ + nsIPresContext *px = mViewManager->GetPresContext(); + nsIWidget *thiswin = GetWidget(); + + if (nsnull == thiswin) + thiswin = GetOffsetFromWidget(nsnull, nsnull); + + if (nsnull != thiswin) + thiswin->BeginResizingChildren(); + + nsView::SetPosition(aX, aY); + + AdjustChildWidgets(this, this, 0, 0, px->GetTwipsToPixels()); + + if (nsnull != thiswin) + { + thiswin->EndResizingChildren(); + NS_RELEASE(thiswin); + } + + NS_RELEASE(px); +} + PRBool nsScrollingView :: Paint(nsIRenderingContext& rc, const nsRect& rect, PRUint32 aPaintFlags, nsIView *aBackstop) { - PRBool retval; + PRBool clipres = PR_FALSE; rc.PushState(); - rc.Translate(-mOffsetX, -mOffsetY); - retval = nsView::Paint(rc, rect, aPaintFlags, aBackstop); - rc.PopState(); - return retval; + if (mVis == nsViewVisibility_kShow) + clipres = rc.SetClipRect(mBounds, nsClipCombine_kIntersect); + + if (clipres == PR_FALSE) + { + rc.Translate(-mOffsetX, -mOffsetY); + clipres = nsView::Paint(rc, rect, aPaintFlags | NS_VIEW_FLAG_CLIP_SET, aBackstop); + } + + clipres = rc.PopState(); + + if ((clipres == PR_FALSE) && (mVis == nsViewVisibility_kShow) && (nsnull == mWindow)) + clipres = rc.SetClipRect(mBounds, nsClipCombine_kSubtract); + + return clipres; } nsEventStatus nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEventFlags) @@ -316,6 +357,9 @@ nsEventStatus nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent nsIWidget *thiswin = GetWidget(); + if (nsnull == thiswin) + thiswin = GetOffsetFromWidget(nsnull, nsnull); + if (nsnull != thiswin) thiswin->BeginResizingChildren(); @@ -328,7 +372,7 @@ nsEventStatus nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent if (dy != 0) { - AdjustChildWidgets(0, dy); + AdjustChildWidgets(this, this, 0, 0, px->GetTwipsToPixels()); if (nsnull != mWindow) mWindow->Scroll(0, dy, &clip); @@ -381,6 +425,9 @@ nsEventStatus nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent nsIWidget *thiswin = GetWidget(); + if (nsnull == thiswin) + thiswin = GetOffsetFromWidget(nsnull, nsnull); + if (nsnull != thiswin) thiswin->BeginResizingChildren(); @@ -393,7 +440,7 @@ nsEventStatus nsScrollingView :: HandleEvent(nsGUIEvent *aEvent, PRUint32 aEvent if (dx != 0) { - AdjustChildWidgets(dx, 0); + AdjustChildWidgets(this, this, 0, 0, px->GetTwipsToPixels()); if (nsnull != mWindow) mWindow->Scroll(dx, 0, &clip); @@ -538,7 +585,7 @@ void nsScrollingView :: ComputeContainerSize() NS_IF_RELEASE(scrollv); if ((dx != 0) || (dy != 0)) - AdjustChildWidgets(dx, dy); + AdjustChildWidgets(this, this, 0, 0, px->GetTwipsToPixels()); NS_RELEASE(px); NS_RELEASE(scrollview); @@ -598,34 +645,92 @@ void nsScrollingView :: GetVisibleOffset(nscoord *aOffsetX, nscoord *aOffsetY) *aOffsetY = mOffsetY; } -void nsScrollingView :: AdjustChildWidgets(nscoord aDx, nscoord aDy) +void nsScrollingView :: AdjustChildWidgets(nsScrollingView *aScrolling, nsIView *aView, nscoord aDx, nscoord aDy, float scale) { - PRInt32 numkids = GetChildCount(); + PRInt32 numkids = aView->GetChildCount(); + nsIScrollableView *scroller; + nscoord offx, offy; + PRBool isscroll = PR_FALSE; + + static NS_DEFINE_IID(kscroller, NS_ISCROLLABLEVIEW_IID); + + if (aScrolling == aView) + { + nsIWidget *widget = aScrolling->GetOffsetFromWidget(&aDx, &aDy); + nsIView *parview = aScrolling->GetParent(); + + while (nsnull != parview) + { + nsIWidget *parwidget = parview->GetWidget(); + + if (NS_OK == parview->QueryInterface(kscroller, (void **)&scroller)) + { + scroller->GetVisibleOffset(&offx, &offy); + + aDx -= offx; + aDy -= offy; + + NS_RELEASE(scroller); + } + + if (parwidget == widget) + { + NS_IF_RELEASE(parwidget); + break; + } + + NS_IF_RELEASE(parwidget); + + parview = parview->GetParent(); + } + + NS_IF_RELEASE(widget); + } + + aView->GetPosition(&offx, &offy); + + aDx += offx; + aDy += offy; + + if (NS_OK == aView->QueryInterface(kscroller, (void **)&scroller)) + { + scroller->GetVisibleOffset(&offx, &offy); + + aDx -= offx; + aDy -= offy; + + NS_RELEASE(scroller); + + isscroll = PR_TRUE; + } for (PRInt32 cnt = 0; cnt < numkids; cnt++) { - nsIView *kid = GetChild(cnt); + nsIView *kid = aView->GetChild(cnt); + nsIWidget *win = kid->GetWidget(); - if ((kid != mVScrollBarView) && (kid != mHScrollBarView)) + if (nsnull != win) { - nsIWidget *win = kid->GetWidget(); + nsRect bounds; - if (nsnull != win) - { - nsRect bounds; + win->BeginResizingChildren(); + kid->GetBounds(bounds); - win->BeginResizingChildren(); - win->GetBounds(bounds); - win->Move(bounds.x + aDx, bounds.y + aDy); - } + if (!isscroll || + (isscroll && + (kid != ((nsScrollingView *)aView)->mVScrollBarView) && + (kid != ((nsScrollingView *)aView)->mHScrollBarView))) + win->Move(NS_TO_INT_ROUND((bounds.x + aDx) * scale), NS_TO_INT_ROUND((bounds.y + aDy) * scale)); + else + win->Move(NS_TO_INT_ROUND((bounds.x + aDx + offx) * scale), NS_TO_INT_ROUND((bounds.y + aDy + offy) * scale)); + } - kid->AdjustChildWidgets(aDx, aDy); + AdjustChildWidgets(aScrolling, kid, aDx, aDy, scale); - if (nsnull != win) - { - win->EndResizingChildren(); - NS_RELEASE(win); - } + if (nsnull != win) + { + win->EndResizingChildren(); + NS_RELEASE(win); } } } diff --git a/view/src/nsScrollingView.h b/view/src/nsScrollingView.h index bd2c196ddc6..9714b04ee10 100644 --- a/view/src/nsScrollingView.h +++ b/view/src/nsScrollingView.h @@ -49,8 +49,9 @@ public: //overrides virtual void SetDimensions(nscoord width, nscoord height); + virtual void SetPosition(nscoord aX, nscoord aY); virtual nsEventStatus HandleEvent(nsGUIEvent *aEvent, PRUint32 aEventFlags); - virtual void AdjustChildWidgets(nscoord aDx, nscoord aDy); + virtual void AdjustChildWidgets(nsScrollingView *aScrolling, nsIView *aView, nscoord aDx, nscoord aDy, float aScale); virtual PRBool Paint(nsIRenderingContext& rc, const nsRect& rect, PRUint32 aPaintFlags, nsIView *aBackstop = nsnull); diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp index ed140270528..2f017f66a76 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -34,6 +34,9 @@ static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); +#define SHOW_VIEW_BORDERS +//#define HIDE_ALL_WIDGETS + // // Main events handler // @@ -142,34 +145,6 @@ nsEventStatus PR_CALLBACK HandleEvent(nsGUIEvent *aEvent) return result; } -// this should be added to nsView. maybe - -nsIWidget * GetWindowTemp(nsIView *aView, nscoord *aDx, nscoord *aDy) -{ - nsIWidget *window = nsnull; - nsIView *ancestor = aView; - - while (nsnull != ancestor) - { - if (nsnull != (window = ancestor->GetWidget())) - return window; - - ancestor = ancestor->GetParent(); - - if ((nsnull != aDx) && (nsnull != aDy)) - { - nscoord offx, offy; - - ancestor->GetPosition(&offx, &offy); - - *aDx += offx; - *aDy += offy; - } - } - - return nsnull; -} - nsView :: nsView() { mVis = nsViewVisibility_kShow; @@ -353,7 +328,7 @@ nsresult nsView :: Init(nsIViewManager* aManager, mWindow->Create(aNative, trect, ::HandleEvent, dx, nsnull, aWidgetInitData); else { - nsIWidget *parent = GetWindowTemp(aParent, nsnull, nsnull); + nsIWidget *parent = GetOffsetFromWidget(nsnull, nsnull); mWindow->Create(parent, trect, ::HandleEvent, dx, nsnull, aWidgetInitData); NS_IF_RELEASE(parent); } @@ -390,35 +365,42 @@ PRBool nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, { nsIView *pRoot = mViewManager->GetRootView(); PRBool clipres = PR_FALSE; + PRBool clipwasset = PR_FALSE; rc.PushState(); - if ((mClip.mLeft != mClip.mRight) && (mClip.mTop != mClip.mBottom)) + if (aPaintFlags & NS_VIEW_FLAG_CLIP_SET) { - nsRect crect; - - crect.x = mClip.mLeft + mBounds.x; - crect.y = mClip.mTop + mBounds.y; - crect.width = mClip.mRight - mClip.mLeft; - crect.height = mClip.mBottom - mClip.mTop; - - clipres = rc.SetClipRect(crect, nsClipCombine_kIntersect); + clipwasset = PR_TRUE; + aPaintFlags &= ~NS_VIEW_FLAG_CLIP_SET; + } + else if (mVis == nsViewVisibility_kShow) + { + if ((mClip.mLeft != mClip.mRight) && (mClip.mTop != mClip.mBottom)) + { + nsRect crect; + + crect.x = mClip.mLeft + mBounds.x; + crect.y = mClip.mTop + mBounds.y; + crect.width = mClip.mRight - mClip.mLeft; + crect.height = mClip.mBottom - mClip.mTop; + + clipres = rc.SetClipRect(crect, nsClipCombine_kIntersect); + } + else if (this != pRoot) + clipres = rc.SetClipRect(mBounds, nsClipCombine_kIntersect); + } + + if (nsnull != mXForm) + { + nsTransform2D *pXForm = rc.GetCurrentTransform(); + pXForm->Concatenate(mXForm); } - else if (this != pRoot) - clipres = rc.SetClipRect(mBounds, nsClipCombine_kIntersect); if (clipres == PR_FALSE) { rc.Translate(mBounds.x, mBounds.y); - //XXX maybe we should set this before we set the clip? MMP - - if (nsnull != mXForm) - { - nsTransform2D *pXForm = rc.GetCurrentTransform(); - pXForm->Concatenate(mXForm); - } - PRInt32 numkids = GetChildCount(); for (PRInt32 cnt = 0; cnt < numkids; cnt++) @@ -430,6 +412,10 @@ PRBool nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, nsRect kidRect; kid->GetBounds(kidRect); nsRect damageArea; +// nsRect damageArea = rect; +// damageArea.x -= mBounds.x; +// damageArea.y -= mBounds.y; +// PRBool overlap = damageArea.IntersectRect(damageArea, kidRect); PRBool overlap = damageArea.IntersectRect(rect, kidRect); if (overlap == PR_TRUE) @@ -445,13 +431,64 @@ PRBool nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, } } - if ((clipres == PR_FALSE) && (mVis == nsViewVisibility_kShow) && (nsnull != mFrame)) + if ((clipres == PR_FALSE) && (mVis == nsViewVisibility_kShow)) { - nsIPresContext *cx = mViewManager->GetPresContext(); - rc.PushState(); - mFrame->Paint(*cx, rc, rect); - rc.PopState(); - NS_RELEASE(cx); + float opacity = GetOpacity(); + + if (opacity > 0.0f) + { + rc.PushState(); + +#if 0 + if (HasTransparency() || (opacity < 1.0f)) + { + nsRect crect; + PRBool goodclip = rc.GetClipRect(crect); + + //walk down rendering only views within this clip + + rc.SetClipRect(crect, nsClipCombine_kReplace); + } +#endif + + if (nsnull != mFrame) + { + nsIPresContext *cx = mViewManager->GetPresContext(); + mFrame->Paint(*cx, rc, rect); + NS_RELEASE(cx); + } + +#ifdef SHOW_VIEW_BORDERS + { + nscoord x, y, w, h; + + if ((mClip.mLeft != mClip.mRight) && (mClip.mTop != mClip.mBottom)) + { + x = mClip.mLeft; + y = mClip.mTop; + w = mClip.mRight - mClip.mLeft; + h = mClip.mBottom - mClip.mTop; + + rc.SetColor(NS_RGB(255, 255, 0)); + } + else + { + x = y = 0; + w = mBounds.width; + h = mBounds.height; + + if (nsnull != mWindow) + rc.SetColor(NS_RGB(0, 255, 0)); + else + rc.SetColor(NS_RGB(0, 0, 255)); + } + + rc.DrawRect(x, y, w, h); + } +#endif + + rc.PopState(); + } } } @@ -459,13 +496,14 @@ PRBool nsView :: Paint(nsIRenderingContext& rc, const nsRect& rect, //state from the stack but doesn't change the state of the underlying graphics //context. MMP - rc.PopState(); + clipres = rc.PopState(); //now we need to exclude this view from the rest of the //paint process. only do this if this view is actually //visible and if there is no widget (like a scrollbar) here. - if ((clipres == PR_FALSE) && (mVis == nsViewVisibility_kShow) && (nsnull == mWindow)) +// if ((clipres == PR_FALSE) && (mVis == nsViewVisibility_kShow)) + if (!clipwasset && (clipres == PR_FALSE) && (mVis == nsViewVisibility_kShow) && (nsnull == mWindow)) { if ((mClip.mLeft != mClip.mRight) && (mClip.mTop != mClip.mBottom)) { @@ -524,7 +562,7 @@ nsEventStatus nsView :: HandleEvent(nsGUIEvent *event, PRUint32 aEventFlags) nsIPresContext *cx = mViewManager->GetPresContext(); nscoord xoff, yoff; - mViewManager->GetWindowOffsets(&xoff, &yoff); + GetScrollOffset(&xoff, &yoff); event->point.x += xoff; event->point.y += yoff; @@ -629,17 +667,12 @@ void nsView :: SetPosition(nscoord x, nscoord y) nsIPresContext *px = mViewManager->GetPresContext(); nscoord offx, offy, parx = 0, pary = 0; float scale = px->GetTwipsToPixels(); - nsIView *par = GetParent(); + nsIWidget *pwidget = nsnull; - mViewManager->GetWindowOffsets(&offx, &offy); + GetScrollOffset(&offx, &offy); - if (nsnull != par) - { - nsIWidget *pwidget = nsnull; - - pwidget = GetWindowTemp(par, &parx, &pary); - NS_IF_RELEASE(pwidget); - } + pwidget = GetOffsetFromWidget(&parx, &pary); + NS_IF_RELEASE(pwidget); mWindow->Move(NS_TO_INT_ROUND((x + parx + offx) * scale), NS_TO_INT_ROUND((y + pary + offy) * scale)); @@ -735,9 +768,11 @@ void nsView :: SetVisibility(nsViewVisibility aVisibility) if (nsnull != mWindow) { +#ifndef HIDE_ALL_WIDGETS if (mVis == nsViewVisibility_kShow) mWindow->Show(PR_TRUE); else +#endif mWindow->Show(PR_FALSE); } } @@ -947,30 +982,52 @@ void nsView :: List(FILE* out, PRInt32 aIndent) const fputs(">\n", out); } -void nsView :: AdjustChildWidgets(nscoord aDx, nscoord aDy) +nsIWidget * nsView :: GetOffsetFromWidget(nscoord *aDx, nscoord *aDy) { - PRInt32 numkids = GetChildCount(); + nsIWidget *window = nsnull; + nsIView *ancestor = GetParent(); - for (PRInt32 cnt = 0; cnt < numkids; cnt++) + while (nsnull != ancestor) { - nsIView *kid = GetChild(cnt); - nsIWidget *win = kid->GetWidget(); + if (nsnull != (window = ancestor->GetWidget())) + return window; - if (nsnull != win) + if ((nsnull != aDx) && (nsnull != aDy)) { - nsRect bounds; + nscoord offx, offy; - win->BeginResizingChildren(); - win->GetBounds(bounds); - win->Move(bounds.x + aDx, bounds.y + aDy); + ancestor->GetPosition(&offx, &offy); + + *aDx += offx; + *aDy += offy; } - kid->AdjustChildWidgets(aDx, aDy); - - if (nsnull != win) - { - win->EndResizingChildren(); - NS_RELEASE(win); - } + ancestor = ancestor->GetParent(); } + + return nsnull; +} + +void nsView :: GetScrollOffset(nscoord *aDx, nscoord *aDy) +{ + nsIWidget *window = nsnull; + nsIView *ancestor = GetParent(); + + while (nsnull != ancestor) + { + nsIScrollableView *sview; + + static NS_DEFINE_IID(kscroller, NS_ISCROLLABLEVIEW_IID); + + if (NS_OK == ancestor->QueryInterface(kscroller, (void **)&sview)) + { + sview->GetVisibleOffset(aDx, aDy); + NS_RELEASE(sview); + return; + } + + ancestor = ancestor->GetParent(); + } + + *aDx = *aDy = 0; } diff --git a/view/src/nsView.h b/view/src/nsView.h index b8a86e85a7b..9c7fc9503bb 100644 --- a/view/src/nsView.h +++ b/view/src/nsView.h @@ -90,7 +90,8 @@ public: virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const; virtual void SetFrame(nsIFrame *aFrame); virtual nsIFrame * GetFrame(); - virtual void AdjustChildWidgets(nscoord aDx, nscoord aDy); + virtual nsIWidget * GetOffsetFromWidget(nscoord *aDx, nscoord *aDy); + virtual void GetScrollOffset(nscoord *aDx, nscoord *aDy); protected: // diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 6e8c1ab7eae..dd19060698f 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -31,6 +31,7 @@ static const PRBool gsDebug = PR_FALSE; #define UPDATE_QUANTUM 1000 / 40 //#define USE_DIRTY_RECT +//#define NO_DOUBLE_BUFFER static void vm_timer_callback(nsITimer *aTimer, void *aClosure) { @@ -288,6 +289,10 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, nsI if (mTransCnt > 0) aUpdateFlags |= NS_VMREFRESH_DOUBLE_BUFFER; +#ifdef NO_DOUBLE_BUFFER + aUpdateFlags &= ~NS_VMREFRESH_DOUBLE_BUFFER; +#endif + if (nsnull == aContext) { localcx = CreateRenderingContext(*aView); @@ -351,6 +356,10 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, nsR if (mTransCnt > 0) aUpdateFlags |= NS_VMREFRESH_DOUBLE_BUFFER; +#ifdef NO_DOUBLE_BUFFER + aUpdateFlags &= ~NS_VMREFRESH_DOUBLE_BUFFER; +#endif + if (nsnull == aContext) { localcx = CreateRenderingContext(*aView); @@ -448,6 +457,7 @@ void nsViewManager :: UpdateView(nsIView *aView, nsIRegion *aRegion, PRUint32 aU nsRect trect; aView->GetBounds(trect); + trect.x = trect.y = 0; UpdateView(aView, trect, aUpdateFlags); } }