From 59427ab6f1c587404a52318f5ba88906a6e7d8b2 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Sat, 22 May 2004 20:04:59 +0000 Subject: [PATCH] Backing out to try and fix mac orange. Bug 243724 --- view/src/nsViewManager.cpp | 94 ++++++----- widget/public/nsIWidget.h | 68 +------- widget/src/cocoa/nsChildView.mm | 27 ++-- widget/src/gtk/nsWidget.cpp | 21 ++- widget/src/gtk/nsWindow.cpp | 56 +++++-- widget/src/gtk2/nsWindow.cpp | 47 ++++-- widget/src/mac/nsChildWindow.cpp | 55 ++++--- widget/src/mac/nsWindow.cpp | 145 +++++++++++------ widget/src/xlib/nsWindow.cpp | 48 ++++-- widget/src/xpwidgets/nsBaseWidget.cpp | 223 +++++++++++++++++++------- widget/src/xpwidgets/nsBaseWidget.h | 22 +++ 11 files changed, 526 insertions(+), 280 deletions(-) diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index a818c7d03ffa..f2eef9b43a47 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -1163,34 +1163,46 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo return; } - for (nsIWidget* childWidget = widget->GetFirstChild(); - childWidget; - childWidget = childWidget->GetNextSibling()) { - PRBool widgetVisible; - childWidget->IsVisible(widgetVisible); - if (widgetVisible) { - nsView* view = nsView::GetViewFor(childWidget); - if (view && view->GetVisibility() == nsViewVisibility_kShow - && !view->GetFloating()) { - nsRect bounds = view->GetBounds(); - if (bounds.width > 0 && bounds.height > 0) { - nsView* viewParent = view->GetParent(); + nsCOMPtr children(dont_AddRef(widget->GetChildren())); + if (!children) { + return; + } + + children->First(); + do { + nsCOMPtr child; + if (!NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) { + return; + } + + nsCOMPtr childWidget = do_QueryInterface(child); + if (childWidget) { + PRBool widgetVisible; + childWidget->IsVisible(widgetVisible); + if (widgetVisible) { + nsView* view = nsView::GetViewFor(childWidget); + if (view && view->GetVisibility() == nsViewVisibility_kShow + && !view->GetFloating()) { + nsRect bounds = view->GetBounds(); + if (bounds.width > 0 && bounds.height > 0) { + nsView* viewParent = view->GetParent(); - while (viewParent && viewParent != aRootView) { - viewParent->ConvertToParentCoords(&bounds.x, &bounds.y); - viewParent = viewParent->GetParent(); - } + while (viewParent && viewParent != aRootView) { + viewParent->ConvertToParentCoords(&bounds.x, &bounds.y); + viewParent = viewParent->GetParent(); + } - // maybe we couldn't get the view into the coordinate - // system of aRootView (maybe it's not a descendant - // view of aRootView?); if so, don't use it - if (viewParent) { - aRgn.Or(aRgn, bounds); + // maybe we couldn't get the view into the coordinate + // system of aRootView (maybe it's not a descendant + // view of aRootView?); if so, don't use it + if (viewParent) { + aRgn.Or(aRgn, bounds); + } } } } } - } + } while (NS_SUCCEEDED(children->Next())); } PRBool nsViewManager::BuildRenderingDisplayList(nsIView* aRootView, @@ -1616,24 +1628,32 @@ PRBool nsViewManager::UpdateWidgetArea(nsView *aWidgetView, const nsRect &aDamag } PRBool childCovers = PR_FALSE; - for (nsIWidget* childWidget = widget->GetFirstChild(); - childWidget; - childWidget = childWidget->GetNextSibling()) { - nsView* view = nsView::GetViewFor(childWidget); - if (nsnull != view) { - nsRect damage = bounds; - nsView* vp = view; - while (vp != aWidgetView && nsnull != vp) { - vp->ConvertFromParentCoords(&damage.x, &damage.y); - vp = vp->GetParent(); - } + nsCOMPtr children(dont_AddRef(widget->GetChildren())); + if (children) { + children->First(); + do { + nsCOMPtr child; + if (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) { + nsCOMPtr childWidget = do_QueryInterface(child); + if (childWidget) { + nsView* view = nsView::GetViewFor(childWidget); + if (nsnull != view) { + nsRect damage = bounds; + nsView* vp = view; + while (vp != aWidgetView && nsnull != vp) { + vp->ConvertFromParentCoords(&damage.x, &damage.y); + vp = vp->GetParent(); + } - if (nsnull != vp) { // vp == nsnull means it's in a different hierarchy so we ignore it - if (UpdateWidgetArea(view, damage, aIgnoreWidgetView)) { - childCovers = PR_TRUE; + if (nsnull != vp) { // vp == nsnull means it's in a different hierarchy so we ignore it + if (UpdateWidgetArea(view, damage, aIgnoreWidgetView)) { + childCovers = PR_TRUE; + } + } + } } } - } + } while (NS_SUCCEEDED(children->Next())); } if (!childCovers) { diff --git a/widget/public/nsIWidget.h b/widget/public/nsIWidget.h index 322ae28a7d3a..16f683b89ec2 100644 --- a/widget/public/nsIWidget.h +++ b/widget/public/nsIWidget.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -46,7 +46,6 @@ #include "prthread.h" #include "nsEvent.h" -#include "nsCOMPtr.h" // forward declarations class nsIAppShell; @@ -257,12 +256,6 @@ class nsIWidget : public nsISupports { NS_DEFINE_STATIC_IID_ACCESSOR(NS_IWIDGET_IID) - nsIWidget() - : mLastChild(nsnull) - , mPrevSibling(nsnull) - {} - - /** * Create and initialize a widget. * @@ -364,48 +357,13 @@ class nsIWidget : public nsISupports { virtual nsIWidget* GetParent(void) = 0; /** - * Return the first child of this widget. Will return null if - * there are no children. + * Return an nsEnumerator over the children of this widget. + * + * @return an enumerator over the list of children or nsnull if it does not + * have any children + * */ - nsIWidget* GetFirstChild() const { - return mFirstChild; - } - - /** - * Return the last child of this widget. Will return null if - * there are no children. - */ - nsIWidget* GetLastChild() const { - return mLastChild; - } - - /** - * Return the next sibling of this widget - */ - nsIWidget* GetNextSibling() const { - return mNextSibling; - } - - /** - * Set the next sibling of this widget - */ - void SetNextSibling(nsIWidget* aSibling) { - mNextSibling = aSibling; - } - - /** - * Return the previous sibling of this widget - */ - nsIWidget* GetPrevSibling() const { - return mPrevSibling; - } - - /** - * Set the previous sibling of this widget - */ - void SetPrevSibling(nsIWidget* aSibling) { - mPrevSibling = aSibling; - } + virtual nsIEnumerator* GetChildren(void) = 0; /** * Show or hide this widget @@ -1017,18 +975,6 @@ class nsIWidget : public nsISupports { */ NS_IMETHOD GetLastInputEventTime(PRUint32& aTime) = 0; - -protected: - // keep the list of children. We also keep track of our siblings. - // The ownership model is as follows: parent holds a strong ref to - // the first element of the list, and each element holds a strong - // ref to the next element in the list. The prevsibling and - // lastchild pointers are weak, which is fine as long as they are - // maintained properly. - nsCOMPtr mFirstChild; - nsIWidget* mLastChild; - nsCOMPtr mNextSibling; - nsIWidget* mPrevSibling; }; #endif // nsIWidget_h__ diff --git a/widget/src/cocoa/nsChildView.mm b/widget/src/cocoa/nsChildView.mm index 6238173ad576..0281ea299e43 100644 --- a/widget/src/cocoa/nsChildView.mm +++ b/widget/src/cocoa/nsChildView.mm @@ -1543,15 +1543,24 @@ NS_IMETHODIMP nsChildView::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) } // Scroll the children (even if the widget is not visible) - for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { - // We use resize rather than move since it gives us control - // over repainting. In the case of blitting, Quickdraw views - // draw their child widgets on the blit, so we can scroll - // like a bat out of hell by not wasting time invalidating - // the widgets, since it's completely unnecessary to do so. - nsRect bounds; - kid->GetBounds(bounds); - kid->Resize(bounds.x + aDx, bounds.y + aDy, bounds.width, bounds.height, PR_FALSE); + nsCOMPtr children(getter_AddRefs(GetChildren())); + if ( children ) { + children->First(); + do { + nsCOMPtr child; + if (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) { + nsCOMPtr widget = do_QueryInterface(child); + + // We use resize rather than move since it gives us control + // over repainting. In the case of blitting, Quickdraw views + // draw their child widgets on the blit, so we can scroll + // like a bat out of hell by not wasting time invalidating + // the widgets, since it's completely unnecessary to do so. + nsRect bounds; + widget->GetBounds(bounds); + widget->Resize(bounds.x + aDx, bounds.y + aDy, bounds.width, bounds.height, PR_FALSE); + } + } while (NS_SUCCEEDED(children->Next())); } if (mVisible) diff --git a/widget/src/gtk/nsWidget.cpp b/widget/src/gtk/nsWidget.cpp index 69b23486f235..91f3abbd9adc 100644 --- a/widget/src/gtk/nsWidget.cpp +++ b/widget/src/gtk/nsWidget.cpp @@ -607,8 +607,10 @@ NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) gtk_widget_set_usize(mWidget, aWidth, aHeight); ResetInternalVisibility(); - for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { - NS_STATIC_CAST(nsWidget*, kid)->ResetInternalVisibility(); + PRInt32 childCount = mChildren.Count(); + PRInt32 index; + for (index = 0; index < childCount; index++) { + NS_STATIC_CAST(nsWidget*, mChildren[index])->ResetInternalVisibility(); } return NS_OK; @@ -2241,8 +2243,19 @@ void nsWidget::ThemeChanged() { // Dispatch a NS_THEMECHANGED event for each of our children, recursively - for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { - NS_STATIC_CAST(nsWidget*, kid)->ThemeChanged(); + nsCOMPtr children = dont_AddRef(GetChildren()); + if (children) { + nsCOMPtr isupp; + + while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))) && isupp) { + + nsWidget* child = NS_REINTERPRET_CAST(nsWidget*, isupp.get()); + child->ThemeChanged(); + + if (NS_FAILED(children->Next())) { + break; + } + } } DispatchStandardEvent(NS_THEMECHANGED); diff --git a/widget/src/gtk/nsWindow.cpp b/widget/src/gtk/nsWindow.cpp index e469d9de524c..879a920d2209 100644 --- a/widget/src/gtk/nsWindow.cpp +++ b/widget/src/gtk/nsWindow.cpp @@ -894,8 +894,26 @@ 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(); + nsCOMPtr children; + + children = dont_AddRef(GetChildren()); + + if (children) { + nsCOMPtr isupp; + + nsCOMPtr child; + while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))) && isupp) { + + child = do_QueryInterface(isupp); + + if (child) { + child->Update(); + } + + if (NS_FAILED(children->Next())) { + break; + } + } } // While I'd think you should NS_RELEASE(aPaintEvent.widget) here, @@ -2207,14 +2225,26 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) } // Update bounds on our child windows - for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { - nsRect bounds; - kid->GetBounds(bounds); - bounds.x += aDx; - bounds.y += aDy; - nsWidget* childWidget = NS_STATIC_CAST(nsWidget*, kid); - childWidget->SetBounds(bounds); - childWidget->ResetInternalVisibility(); + nsCOMPtr children = dont_AddRef(GetChildren()); + if (children) { + nsCOMPtr isupp; + nsCOMPtr child; + while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp)) && isupp)) { + child = do_QueryInterface(isupp); + + if (child) { + nsRect bounds; + child->GetBounds(bounds); + bounds.x += aDx; + bounds.y += aDy; + nsWidget* childWidget = NS_STATIC_CAST(nsWidget*, NS_STATIC_CAST(nsIWidget*, child.get())); + childWidget->SetBounds(bounds); + childWidget->ResetInternalVisibility(); + } + + if (NS_FAILED(children->Next())) + break; + } } return NS_OK; @@ -2694,8 +2724,10 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint) mBounds.height = aHeight; ResetInternalVisibility(); - for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { - NS_STATIC_CAST(nsWidget*, kid)->ResetInternalVisibility(); + PRInt32 childCount = mChildren.Count(); + PRInt32 index; + for (index = 0; index < childCount; index++) { + NS_STATIC_CAST(nsWidget*, mChildren[index])->ResetInternalVisibility(); } // code to keep the window from showing before it has been moved or resized diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index 14a1caa69e3f..46785cc06573 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -346,13 +346,21 @@ nsWindow::Destroy(void) NativeShow(PR_FALSE); - // walk the list of children and call destroy on them. Have to be - // careful, though -- calling destroy on a kid may actually remove - // it from our child list, losing its sibling links. - for (nsIWidget* kid = mFirstChild; kid; ) { - nsIWidget* next = kid->GetNextSibling(); - kid->Destroy(); - kid = next; + // walk the list of children and call destroy on them. + nsCOMPtr children = dont_AddRef(GetChildren()); + if (children) { + nsCOMPtr isupp; + nsCOMPtr child; + while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp)) + && isupp)) { + child = do_QueryInterface(isupp); + if (child) { + child->Destroy(); + } + + if (NS_FAILED(children->Next())) + break; + } } #ifdef USE_XIM @@ -827,12 +835,25 @@ nsWindow::Scroll(PRInt32 aDx, moz_drawingarea_scroll(mDrawingarea, aDx, aDy); // Update bounds on our child windows - for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { - nsRect bounds; - kid->GetBounds(bounds); - bounds.x += aDx; - bounds.y += aDy; - NS_STATIC_CAST(nsBaseWidget*, kid)->SetBounds(bounds); + nsCOMPtr children = dont_AddRef(GetChildren()); + if (children) { + nsCOMPtr isupp; + nsCOMPtr child; + while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp)) + && isupp)) { + child = do_QueryInterface(isupp); + if (child) { + nsRect bounds; + child->GetBounds(bounds); + bounds.x += aDx; + bounds.y += aDy; + NS_STATIC_CAST(nsBaseWidget*, + (nsIWidget*)child)->SetBounds(bounds); + } + + if (NS_FAILED(children->Next())) + break; + } } // Process all updates so that everything is drawn. diff --git a/widget/src/mac/nsChildWindow.cpp b/widget/src/mac/nsChildWindow.cpp index 3a1c9e1ab7c7..e4f1857774e6 100644 --- a/widget/src/mac/nsChildWindow.cpp +++ b/widget/src/mac/nsChildWindow.cpp @@ -97,33 +97,36 @@ void nsChildWindow::CalcWindowRegions() // clip the siblings out of the window region and visRegion if (mClipSiblings && mParent && !mIsTopWidgetWindow) { // need to walk the siblings backwards, to get clipping right. - nsIWidget* sibling = mParent->GetLastChild(); - NS_ASSERTION(sibling, "We're in the list, so it better have a last child!"); - StRegionFromPool siblingRgn; - if (siblingRgn == nsnull) - return; - - do { - if (sibling == NS_STATIC_CAST(nsIWidget*, this)) - break; - - PRBool visible; - sibling->IsVisible(visible); - if (visible) { // don't clip if not visible. - // get sibling's bounds in parent's coordinate system. - nsRect siblingRect; - sibling->GetBounds(siblingRect); + nsCOMPtr siblings = getter_AddRefs((nsIBidirectionalEnumerator*)mParent->GetChildren()); + if (siblings && NS_SUCCEEDED(siblings->Last())) { + StRegionFromPool siblingRgn; + if (siblingRgn == nsnull) + return; + do { + // when we reach ourself, stop clipping. + nsCOMPtr item; + if (NS_FAILED(siblings->CurrentItem(getter_AddRefs(item))) || + item == NS_STATIC_CAST(nsIWidget*, this)) + break; + + nsCOMPtr sibling(do_QueryInterface(item)); + PRBool visible; + sibling->IsVisible(visible); + if (visible) { // don't clip if not visible. + // get sibling's bounds in parent's coordinate system. + nsRect siblingRect; + sibling->GetBounds(siblingRect); - // transform from parent's coordinate system to widget coordinates. - siblingRect.MoveBy(-mBounds.x, -mBounds.y); + // transform from parent's coordinate system to widget coordinates. + siblingRect.MoveBy(-mBounds.x, -mBounds.y); - Rect macRect; - ::SetRect(&macRect, siblingRect.x, siblingRect.y, siblingRect.XMost(), siblingRect.YMost()); - ::RectRgn(siblingRgn, &macRect); - ::DiffRgn(mWindowRegion, siblingRgn, mWindowRegion); - ::DiffRgn(mVisRegion, siblingRgn, mVisRegion); - } - sibling = sibling->GetPrevSibling(); - } while (sibling); + Rect macRect; + ::SetRect(&macRect, siblingRect.x, siblingRect.y, siblingRect.XMost(), siblingRect.YMost()); + ::RectRgn(siblingRgn, &macRect); + ::DiffRgn(mWindowRegion, siblingRgn, mWindowRegion); + ::DiffRgn(mVisRegion, siblingRgn, mVisRegion); + } + } while (NS_SUCCEEDED(siblings->Prev())); + } } } diff --git a/widget/src/mac/nsWindow.cpp b/widget/src/mac/nsWindow.cpp index 6e944da772a6..f5df818e91b9 100644 --- a/widget/src/mac/nsWindow.cpp +++ b/widget/src/mac/nsWindow.cpp @@ -298,9 +298,21 @@ nsWindow::nsWindow() : nsBaseWidget() , nsDeleteObserved(this), nsIKBStateContro nsWindow::~nsWindow() { // notify the children that we're gone - for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { - nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid); - childWindow->mParent = nsnull; + nsCOMPtr children ( getter_AddRefs(GetChildren()) ); + if (children) + { + children->First(); + do + { + nsISupports* child; + if (NS_SUCCEEDED(children->CurrentItem(&child))) + { + nsWindow* childWindow = static_cast(static_cast(child)); + NS_RELEASE(child); + + childWindow->mParent = nsnull; + } + } while (NS_SUCCEEDED(children->Next())); } mDestructorCalled = PR_TRUE; @@ -1725,27 +1737,36 @@ void nsWindow::UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext) // and it does for the most part. However; certain cases, such as overlapping // areas that are handled by different view managers, don't properly clip siblings. #ifdef FRONT_TO_BACK -# define FIRST_CHILD() (mFirstChild) -# define NEXT_CHILD(child) (child->GetNextSibling()) +# define FIRST_CHILD(children) (children->Last()) +# define NEXT_CHILD(children) (children->Prev()) #else -# define FIRST_CHILD() (mLastChild) -# define NEXT_CHILD(child) (child->GetPrevSibling()) +# define FIRST_CHILD(children) (children->First()) +# define NEXT_CHILD(children) (children->Next()) #endif // recursively draw the children - for (nsIWidget* kid = FIRST_CHILD(); kid; kid = NEXT_CHILD(kid)) { - nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid); + nsCOMPtr children(getter_AddRefs((nsIBidirectionalEnumerator*)GetChildren())); + if (children) { + FIRST_CHILD(children); + do { + nsISupports* child; + if (NS_SUCCEEDED(children->CurrentItem(&child))) { + nsWindow* childWindow = static_cast(static_cast(child)); - nsRect childBounds; - childWindow->GetBounds(childBounds); + nsRect childBounds; + childWindow->GetBounds(childBounds); - // redraw only the intersection of the child rect and the update rect - nsRect intersection; - if (intersection.IntersectRect(aRect, childBounds)) - { - intersection.MoveBy(-childBounds.x, -childBounds.y); - childWindow->UpdateWidget(intersection, aContext); - } + // redraw only the intersection of the child rect and the update rect + nsRect intersection; + if (intersection.IntersectRect(aRect, childBounds)) + { + intersection.MoveBy(-childBounds.x, -childBounds.y); + childWindow->UpdateWidget(intersection, aContext); + } + + NS_RELEASE(child); + } + } while (NS_SUCCEEDED(NEXT_CHILD(children))); } #undef FIRST_CHILD @@ -1935,14 +1956,25 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) scrollChildren: //-------- // Scroll the children - for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { - nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid); + nsCOMPtr children ( getter_AddRefs(GetChildren()) ); + if (children) + { + children->First(); + do + { + nsISupports* child; + if (NS_SUCCEEDED(children->CurrentItem(&child))) + { + nsWindow* childWindow = static_cast(static_cast(child)); + NS_RELEASE(child); - nsRect bounds; - childWindow->GetBounds(bounds); - bounds.x += aDx; - bounds.y += aDy; - childWindow->SetBounds(bounds); + nsRect bounds; + childWindow->GetBounds(bounds); + bounds.x += aDx; + bounds.y += aDy; + childWindow->SetBounds(bounds); + } + } while (NS_SUCCEEDED(children->Next())); } // recalculate the window regions @@ -2182,29 +2214,33 @@ void nsWindow::CalcWindowRegions() ::CopyRgn(mWindowRegion, mVisRegion); // clip the children out of the visRegion - if (mFirstChild) + nsCOMPtr children ( getter_AddRefs(GetChildren()) ); + if (children) { StRegionFromPool childRgn; if (childRgn != nsnull) { - nsIWidget* child = mFirstChild; + children->First(); do { - nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, child); + nsISupports* child; + if (NS_SUCCEEDED(children->CurrentItem(&child))) + { + nsWindow* childWindow = static_cast(static_cast(child)); + NS_RELEASE(child); - PRBool visible; - childWindow->IsVisible(visible); - if (visible) { - nsRect childRect; - childWindow->GetBounds(childRect); + PRBool visible; + childWindow->IsVisible(visible); + if (visible) { + nsRect childRect; + childWindow->GetBounds(childRect); - Rect macRect; - ::SetRect(&macRect, childRect.x, childRect.y, childRect.XMost(), childRect.YMost()); - ::RectRgn(childRgn, &macRect); - ::DiffRgn(mVisRegion, childRgn, mVisRegion); + Rect macRect; + ::SetRect(&macRect, childRect.x, childRect.y, childRect.XMost(), childRect.YMost()); + ::RectRgn(childRgn, &macRect); + ::DiffRgn(mVisRegion, childRgn, mVisRegion); + } } - - child = child->GetNextSibling(); - } while (child); + } while (NS_SUCCEEDED(children->Next())); } } } @@ -2306,16 +2342,29 @@ nsWindow* nsWindow::FindWidgetHit(Point aThePoint) nsWindow* widgetHit = this; - // traverse through all the nsWindows to find out who got hit, lowest level of course - for (nsIWidget* kid = mLastChild; kid; kid = kid->GetPrevSibling()) { - nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid); - - nsWindow* deeperHit = childWindow->FindWidgetHit(aThePoint); - if (deeperHit) + nsCOMPtr normalEnum ( getter_AddRefs(GetChildren()) ); + nsCOMPtr children ( do_QueryInterface(normalEnum) ); + if (children) + { + // traverse through all the nsWindows to find out who got hit, lowest level of course + children->Last(); + do { - widgetHit = deeperHit; - break; + nsISupports* child; + if (NS_SUCCEEDED(children->CurrentItem(&child))) + { + nsWindow* childWindow = static_cast(static_cast(child)); + NS_RELEASE(child); + + nsWindow* deeperHit = childWindow->FindWidgetHit(aThePoint); + if (deeperHit) + { + widgetHit = deeperHit; + break; + } + } } + while (NS_SUCCEEDED(children->Prev())); } return widgetHit; diff --git a/widget/src/xlib/nsWindow.cpp b/widget/src/xlib/nsWindow.cpp index 325fa89a3e7c..3f6da006e82f 100644 --- a/widget/src/xlib/nsWindow.cpp +++ b/widget/src/xlib/nsWindow.cpp @@ -605,8 +605,26 @@ 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(); + nsCOMPtr children; + + children = dont_AddRef(GetChildren()); + + if (children) { + nsCOMPtr isupp; + + nsCOMPtr child; + while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))) && isupp) { + + child = do_QueryInterface(isupp); + + if (child) { + child->Update(); + } + + if (NS_FAILED(children->Next())) { + break; + } + } } // While I'd think you should NS_RELEASE(aPaintEvent.widget) here, @@ -677,13 +695,25 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) //-------- // Scroll the children - for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { - childWindow = NS_STATIC_CAST(nsWindow*, kid); - nsRect bounds; - childWindow->GetRequestedBounds(bounds); - childWindow->Move(bounds.x + aDx, bounds.y + aDy); - Invalidate(bounds, PR_TRUE); - } + nsCOMPtr children ( getter_AddRefs(GetChildren()) ); + if (children) + { + children->First(); + do + { + nsISupports* child; + if (NS_SUCCEEDED(children->CurrentItem(&child))) + { + nsWindow *childWindow = NS_STATIC_CAST(nsWindow*, NS_STATIC_CAST(nsIWidget*, child)); + NS_RELEASE(child); + + nsRect bounds; + childWindow->GetRequestedBounds(bounds); + childWindow->Move(bounds.x + aDx, bounds.y + aDy); + Invalidate(bounds, PR_TRUE); + } + } while (NS_SUCCEEDED(children->Next())); + } // If we are obscurred by another window we have to update those areas // which were not copied with the XCopyArea function. diff --git a/widget/src/xpwidgets/nsBaseWidget.cpp b/widget/src/xpwidgets/nsBaseWidget.cpp index 5ea0cd5f0f21..ec6ac171a55a 100644 --- a/widget/src/xpwidgets/nsBaseWidget.cpp +++ b/widget/src/xpwidgets/nsBaseWidget.cpp @@ -62,6 +62,9 @@ static PRInt32 gNumWidgets; // nsBaseWidget NS_IMPL_ISUPPORTS1(nsBaseWidget, nsIWidget) +// nsBaseWidget::Enumerator +NS_IMPL_ISUPPORTS2(nsBaseWidget::Enumerator, nsIBidirectionalEnumerator, nsIEnumerator) + //------------------------------------------------------------------------- // @@ -238,9 +241,6 @@ NS_IMETHODIMP nsBaseWidget::SetClientData(void* aClientData) //------------------------------------------------------------------------- NS_METHOD nsBaseWidget::Destroy() { - // Just in case our parent is the only ref to us - nsCOMPtr kungFuDeathGrip(this); - // disconnect from the parent nsIWidget *parent = GetParent(); if (parent) { @@ -277,6 +277,23 @@ nsIWidget* nsBaseWidget::GetParent(void) return nsnull; } +//------------------------------------------------------------------------- +// +// Get this nsBaseWidget's list of children +// +//------------------------------------------------------------------------- +nsIEnumerator* nsBaseWidget::GetChildren() +{ + nsIEnumerator* children = nsnull; + + if (mChildren.Count()) { + children = new Enumerator(*this); + NS_IF_ADDREF(children); + } + return children; +} + + //------------------------------------------------------------------------- // // Add a child to the list of children @@ -284,19 +301,7 @@ nsIWidget* nsBaseWidget::GetParent(void) //------------------------------------------------------------------------- void nsBaseWidget::AddChild(nsIWidget* aChild) { - NS_PRECONDITION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(), - "aChild not properly removed from its old child list"); - - if (!mFirstChild) { - mFirstChild = mLastChild = aChild; - } else { - // append to the list - NS_ASSERTION(mLastChild, "Bogus state"); - NS_ASSERTION(!mLastChild->GetNextSibling(), "Bogus state"); - mLastChild->SetNextSibling(aChild); - aChild->SetPrevSibling(mLastChild); - mLastChild = aChild; - } + mChildren.AppendObject(aChild); } @@ -307,29 +312,7 @@ void nsBaseWidget::AddChild(nsIWidget* aChild) //------------------------------------------------------------------------- void nsBaseWidget::RemoveChild(nsIWidget* aChild) { - NS_ASSERTION(aChild->GetParent() == NS_STATIC_CAST(nsIWidget*, this), - "Not one of our kids!"); - - if (mLastChild == aChild) { - mLastChild = mLastChild->GetPrevSibling(); - } - if (mFirstChild == aChild) { - mFirstChild = mFirstChild->GetNextSibling(); - } - - // Now remove from the list. Make sure that we pass ownership of the tail - // of the list correctly before we have aChild let go of it. - nsIWidget* prev = aChild->GetPrevSibling(); - nsIWidget* next = aChild->GetNextSibling(); - if (prev) { - prev->SetNextSibling(next); - } - if (next) { - next->SetPrevSibling(prev); - } - - aChild->SetNextSibling(nsnull); - aChild->SetPrevSibling(nsnull); + mChildren.RemoveObject(aChild); } @@ -345,36 +328,26 @@ NS_IMETHODIMP nsBaseWidget::SetZIndex(PRInt32 aZIndex) // reorder this child in its parent's list. nsBaseWidget* parent = NS_STATIC_CAST(nsBaseWidget*, GetParent()); if (parent) { - parent->RemoveChild(this); - // Scope sib outside the for loop so we can check it afterward - nsIWidget* sib = parent->GetFirstChild(); - for ( ; sib; sib = sib->GetNextSibling()) { + parent->mChildren.RemoveObject(this); + PRInt32 childCount = parent->mChildren.Count(); + PRInt32 index; + // XXXbz would a binary search for the right insertion point be + // better? How long does this list get? + for (index = 0; index < childCount; index++) { + nsIWidget* childWidget = parent->mChildren[index]; PRInt32 childZIndex; - if (NS_SUCCEEDED(sib->GetZIndex(&childZIndex))) { + if (NS_SUCCEEDED(childWidget->GetZIndex(&childZIndex))) { if (aZIndex < childZIndex) { - // Insert ourselves before sib - nsIWidget* prev = sib->GetPrevSibling(); - mNextSibling = sib; - mPrevSibling = prev; - sib->SetPrevSibling(this); - if (prev) { - prev->SetNextSibling(this); - } else { - NS_ASSERTION(sib == parent->mFirstChild, "Broken child list"); - // We've taken ownership of sib, so it's safe to have parent let - // go of it - parent->mFirstChild = this; - } - PlaceBehind(eZPlacementBelow, sib, PR_FALSE); + parent->mChildren.InsertObjectAt(this, index); + PlaceBehind(eZPlacementBelow, childWidget, PR_FALSE); break; } } } // were we added to the list? - if (!sib) { - parent->AddChild(this); + if (index == childCount) { + parent->mChildren.AppendObject(this); } - NS_RELEASE(parent); } return NS_OK; @@ -1302,3 +1275,131 @@ nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut, #endif // DEBUG + + + + + + + + + + + + + + + + + + + + + +//------------------------------------------------------------------------- +// +// Constructor +// +//------------------------------------------------------------------------- + +nsBaseWidget::Enumerator::Enumerator(nsBaseWidget & inParent) + : mCurrentPosition(0), mParent(inParent) +{ +} + + +//------------------------------------------------------------------------- +// +// Destructor +// +//------------------------------------------------------------------------- +nsBaseWidget::Enumerator::~Enumerator() +{ +} + + +//enumerator interfaces +NS_IMETHODIMP +nsBaseWidget::Enumerator::Next() +{ + if (mCurrentPosition < mParent.mChildren.Count() - 1 ) + mCurrentPosition ++; + else + return NS_ERROR_FAILURE; + return NS_OK; +} + + + +NS_IMETHODIMP +nsBaseWidget::Enumerator::Prev() +{ + if (mCurrentPosition > 0 ) + mCurrentPosition --; + else + return NS_ERROR_FAILURE; + return NS_OK; +} + + + +NS_IMETHODIMP +nsBaseWidget::Enumerator::CurrentItem(nsISupports **aItem) +{ + if (!aItem) + return NS_ERROR_NULL_POINTER; + + if ( mCurrentPosition < mParent.mChildren.Count() ) + NS_IF_ADDREF(*aItem = mParent.mChildren[mCurrentPosition]); + else + return NS_ERROR_FAILURE; + + return NS_OK; +} + + + +NS_IMETHODIMP +nsBaseWidget::Enumerator::First() +{ + if ( mParent.mChildren.Count() ) { + mCurrentPosition = 0; + return NS_OK; + } + else + return NS_ERROR_FAILURE; + + return NS_OK; +} + + + +NS_IMETHODIMP +nsBaseWidget::Enumerator::Last() +{ + PRInt32 itemCount = mParent.mChildren.Count(); + if ( itemCount ) { + mCurrentPosition = itemCount - 1; + return NS_OK; + } + else + return NS_ERROR_FAILURE; + + return NS_OK; +} + + + +NS_IMETHODIMP +nsBaseWidget::Enumerator::IsDone() +{ + PRInt32 itemCount = mParent.mChildren.Count(); + + if ((mCurrentPosition == itemCount-1) || (itemCount == 0) ){ //empty lists always return done + return NS_OK; + } + else { + return NS_ENUMERATOR_FALSE; + } + return NS_OK; +} diff --git a/widget/src/xpwidgets/nsBaseWidget.h b/widget/src/xpwidgets/nsBaseWidget.h index e244bb1dc5b7..d604b3b549a9 100644 --- a/widget/src/xpwidgets/nsBaseWidget.h +++ b/widget/src/xpwidgets/nsBaseWidget.h @@ -39,6 +39,7 @@ #include "nsRect.h" #include "nsIWidget.h" +#include "nsIEnumerator.h" #include "nsIMouseListener.h" #include "nsIEventListener.h" #include "nsIMenuListener.h" @@ -46,6 +47,7 @@ #include "nsIAppShell.h" #include "nsString.h" #include "nsVoidArray.h" +#include "nsCOMArray.h" #include "nsCOMPtr.h" #include "nsGUIEvent.h" @@ -78,6 +80,7 @@ public: NS_IMETHOD Destroy(); NS_IMETHOD SetParent(nsIWidget* aNewParent); virtual nsIWidget* GetParent(void); + virtual nsIEnumerator* GetChildren(); virtual void AddChild(nsIWidget* aChild); virtual void RemoveChild(nsIWidget* aChild); @@ -172,7 +175,26 @@ protected: nsRect* mOriginalBounds; PRInt32 mZIndex; nsSizeMode mSizeMode; + + // keep the list of children + nsCOMArray mChildren; + class Enumerator : public nsIBidirectionalEnumerator { + public: + NS_DECL_ISUPPORTS + + Enumerator(nsBaseWidget & inParent); + virtual ~Enumerator(); + + NS_DECL_NSIENUMERATOR + NS_DECL_NSIBIDIRECTIONALENUMERATOR + + private: + PRInt32 mCurrentPosition; + nsBaseWidget& mParent; + }; + friend class Enumerator; + // Enumeration of the methods which are accessable on the "main GUI thread" // via the CallMethod(...) mechanism... // see nsSwitchToUIThread