Backing out to try and fix mac orange. Bug 243724

This commit is contained in:
bzbarsky%mit.edu 2004-05-22 20:04:59 +00:00
Родитель f79a6813af
Коммит 8d3347a058
11 изменённых файлов: 526 добавлений и 280 удалений

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

@ -1163,9 +1163,20 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo
return; return;
} }
for (nsIWidget* childWidget = widget->GetFirstChild(); nsCOMPtr<nsIEnumerator> children(dont_AddRef(widget->GetChildren()));
childWidget; if (!children) {
childWidget = childWidget->GetNextSibling()) { return;
}
children->First();
do {
nsCOMPtr<nsISupports> child;
if (!NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) {
return;
}
nsCOMPtr<nsIWidget> childWidget = do_QueryInterface(child);
if (childWidget) {
PRBool widgetVisible; PRBool widgetVisible;
childWidget->IsVisible(widgetVisible); childWidget->IsVisible(widgetVisible);
if (widgetVisible) { if (widgetVisible) {
@ -1191,6 +1202,7 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo
} }
} }
} }
} while (NS_SUCCEEDED(children->Next()));
} }
PRBool nsViewManager::BuildRenderingDisplayList(nsIView* aRootView, PRBool nsViewManager::BuildRenderingDisplayList(nsIView* aRootView,
@ -1616,9 +1628,14 @@ PRBool nsViewManager::UpdateWidgetArea(nsView *aWidgetView, const nsRect &aDamag
} }
PRBool childCovers = PR_FALSE; PRBool childCovers = PR_FALSE;
for (nsIWidget* childWidget = widget->GetFirstChild(); nsCOMPtr<nsIEnumerator> children(dont_AddRef(widget->GetChildren()));
childWidget; if (children) {
childWidget = childWidget->GetNextSibling()) { children->First();
do {
nsCOMPtr<nsISupports> child;
if (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) {
nsCOMPtr<nsIWidget> childWidget = do_QueryInterface(child);
if (childWidget) {
nsView* view = nsView::GetViewFor(childWidget); nsView* view = nsView::GetViewFor(childWidget);
if (nsnull != view) { if (nsnull != view) {
nsRect damage = bounds; nsRect damage = bounds;
@ -1635,6 +1652,9 @@ PRBool nsViewManager::UpdateWidgetArea(nsView *aWidgetView, const nsRect &aDamag
} }
} }
} }
}
} while (NS_SUCCEEDED(children->Next()));
}
if (!childCovers) { if (!childCovers) {
nsViewManager* vm = aWidgetView->GetViewManager(); nsViewManager* vm = aWidgetView->GetViewManager();

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

@ -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 ***** /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
* *
@ -46,7 +46,6 @@
#include "prthread.h" #include "prthread.h"
#include "nsEvent.h" #include "nsEvent.h"
#include "nsCOMPtr.h"
// forward declarations // forward declarations
class nsIAppShell; class nsIAppShell;
@ -257,12 +256,6 @@ class nsIWidget : public nsISupports {
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IWIDGET_IID) NS_DEFINE_STATIC_IID_ACCESSOR(NS_IWIDGET_IID)
nsIWidget()
: mLastChild(nsnull)
, mPrevSibling(nsnull)
{}
/** /**
* Create and initialize a widget. * Create and initialize a widget.
* *
@ -364,48 +357,13 @@ class nsIWidget : public nsISupports {
virtual nsIWidget* GetParent(void) = 0; virtual nsIWidget* GetParent(void) = 0;
/** /**
* Return the first child of this widget. Will return null if * Return an nsEnumerator over the children of this widget.
* there are no children. *
* @return an enumerator over the list of children or nsnull if it does not
* have any children
*
*/ */
nsIWidget* GetFirstChild() const { virtual nsIEnumerator* GetChildren(void) = 0;
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;
}
/** /**
* Show or hide this widget * Show or hide this widget
@ -1017,18 +975,6 @@ class nsIWidget : public nsISupports {
*/ */
NS_IMETHOD GetLastInputEventTime(PRUint32& aTime) = 0; 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<nsIWidget> mFirstChild;
nsIWidget* mLastChild;
nsCOMPtr<nsIWidget> mNextSibling;
nsIWidget* mPrevSibling;
}; };
#endif // nsIWidget_h__ #endif // nsIWidget_h__

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

@ -1543,15 +1543,24 @@ NS_IMETHODIMP nsChildView::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
} }
// Scroll the children (even if the widget is not visible) // Scroll the children (even if the widget is not visible)
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { nsCOMPtr<nsIEnumerator> children(getter_AddRefs(GetChildren()));
if ( children ) {
children->First();
do {
nsCOMPtr<nsISupports> child;
if (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) {
nsCOMPtr<nsIWidget> widget = do_QueryInterface(child);
// We use resize rather than move since it gives us control // We use resize rather than move since it gives us control
// over repainting. In the case of blitting, Quickdraw views // over repainting. In the case of blitting, Quickdraw views
// draw their child widgets on the blit, so we can scroll // draw their child widgets on the blit, so we can scroll
// like a bat out of hell by not wasting time invalidating // like a bat out of hell by not wasting time invalidating
// the widgets, since it's completely unnecessary to do so. // the widgets, since it's completely unnecessary to do so.
nsRect bounds; nsRect bounds;
kid->GetBounds(bounds); widget->GetBounds(bounds);
kid->Resize(bounds.x + aDx, bounds.y + aDy, bounds.width, bounds.height, PR_FALSE); widget->Resize(bounds.x + aDx, bounds.y + aDy, bounds.width, bounds.height, PR_FALSE);
}
} while (NS_SUCCEEDED(children->Next()));
} }
if (mVisible) if (mVisible)

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

@ -607,8 +607,10 @@ NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
gtk_widget_set_usize(mWidget, aWidth, aHeight); gtk_widget_set_usize(mWidget, aWidth, aHeight);
ResetInternalVisibility(); ResetInternalVisibility();
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { PRInt32 childCount = mChildren.Count();
NS_STATIC_CAST(nsWidget*, kid)->ResetInternalVisibility(); PRInt32 index;
for (index = 0; index < childCount; index++) {
NS_STATIC_CAST(nsWidget*, mChildren[index])->ResetInternalVisibility();
} }
return NS_OK; return NS_OK;
@ -2241,8 +2243,19 @@ void
nsWidget::ThemeChanged() nsWidget::ThemeChanged()
{ {
// Dispatch a NS_THEMECHANGED event for each of our children, recursively // Dispatch a NS_THEMECHANGED event for each of our children, recursively
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { nsCOMPtr<nsIEnumerator> children = dont_AddRef(GetChildren());
NS_STATIC_CAST(nsWidget*, kid)->ThemeChanged(); if (children) {
nsCOMPtr<nsISupports> 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); DispatchStandardEvent(NS_THEMECHANGED);

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

@ -894,8 +894,26 @@ NS_IMETHODIMP nsWindow::Update(void)
// The view manager also expects us to force our // The view manager also expects us to force our
// children to update too! // children to update too!
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { nsCOMPtr<nsIEnumerator> children;
kid->Update();
children = dont_AddRef(GetChildren());
if (children) {
nsCOMPtr<nsISupports> isupp;
nsCOMPtr<nsIWidget> 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, // While I'd think you should NS_RELEASE(aPaintEvent.widget) here,
@ -2207,16 +2225,28 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
} }
// Update bounds on our child windows // Update bounds on our child windows
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { nsCOMPtr<nsIEnumerator> children = dont_AddRef(GetChildren());
if (children) {
nsCOMPtr<nsISupports> isupp;
nsCOMPtr<nsIWidget> child;
while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp)) && isupp)) {
child = do_QueryInterface(isupp);
if (child) {
nsRect bounds; nsRect bounds;
kid->GetBounds(bounds); child->GetBounds(bounds);
bounds.x += aDx; bounds.x += aDx;
bounds.y += aDy; bounds.y += aDy;
nsWidget* childWidget = NS_STATIC_CAST(nsWidget*, kid); nsWidget* childWidget = NS_STATIC_CAST(nsWidget*, NS_STATIC_CAST(nsIWidget*, child.get()));
childWidget->SetBounds(bounds); childWidget->SetBounds(bounds);
childWidget->ResetInternalVisibility(); childWidget->ResetInternalVisibility();
} }
if (NS_FAILED(children->Next()))
break;
}
}
return NS_OK; return NS_OK;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -2694,8 +2724,10 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
mBounds.height = aHeight; mBounds.height = aHeight;
ResetInternalVisibility(); ResetInternalVisibility();
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { PRInt32 childCount = mChildren.Count();
NS_STATIC_CAST(nsWidget*, kid)->ResetInternalVisibility(); 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 // code to keep the window from showing before it has been moved or resized

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

@ -346,13 +346,21 @@ nsWindow::Destroy(void)
NativeShow(PR_FALSE); NativeShow(PR_FALSE);
// walk the list of children and call destroy on them. Have to be // walk the list of children and call destroy on them.
// careful, though -- calling destroy on a kid may actually remove nsCOMPtr<nsIEnumerator> children = dont_AddRef(GetChildren());
// it from our child list, losing its sibling links. if (children) {
for (nsIWidget* kid = mFirstChild; kid; ) { nsCOMPtr<nsISupports> isupp;
nsIWidget* next = kid->GetNextSibling(); nsCOMPtr<nsIWidget> child;
kid->Destroy(); while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))
kid = next; && isupp)) {
child = do_QueryInterface(isupp);
if (child) {
child->Destroy();
}
if (NS_FAILED(children->Next()))
break;
}
} }
#ifdef USE_XIM #ifdef USE_XIM
@ -827,12 +835,25 @@ nsWindow::Scroll(PRInt32 aDx,
moz_drawingarea_scroll(mDrawingarea, aDx, aDy); moz_drawingarea_scroll(mDrawingarea, aDx, aDy);
// Update bounds on our child windows // Update bounds on our child windows
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { nsCOMPtr<nsIEnumerator> children = dont_AddRef(GetChildren());
if (children) {
nsCOMPtr<nsISupports> isupp;
nsCOMPtr<nsIWidget> child;
while (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(isupp))
&& isupp)) {
child = do_QueryInterface(isupp);
if (child) {
nsRect bounds; nsRect bounds;
kid->GetBounds(bounds); child->GetBounds(bounds);
bounds.x += aDx; bounds.x += aDx;
bounds.y += aDy; bounds.y += aDy;
NS_STATIC_CAST(nsBaseWidget*, kid)->SetBounds(bounds); NS_STATIC_CAST(nsBaseWidget*,
(nsIWidget*)child)->SetBounds(bounds);
}
if (NS_FAILED(children->Next()))
break;
}
} }
// Process all updates so that everything is drawn. // Process all updates so that everything is drawn.

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

@ -97,16 +97,19 @@ void nsChildWindow::CalcWindowRegions()
// clip the siblings out of the window region and visRegion // clip the siblings out of the window region and visRegion
if (mClipSiblings && mParent && !mIsTopWidgetWindow) { if (mClipSiblings && mParent && !mIsTopWidgetWindow) {
// need to walk the siblings backwards, to get clipping right. // need to walk the siblings backwards, to get clipping right.
nsIWidget* sibling = mParent->GetLastChild(); nsCOMPtr<nsIBidirectionalEnumerator> siblings = getter_AddRefs((nsIBidirectionalEnumerator*)mParent->GetChildren());
NS_ASSERTION(sibling, "We're in the list, so it better have a last child!"); if (siblings && NS_SUCCEEDED(siblings->Last())) {
StRegionFromPool siblingRgn; StRegionFromPool siblingRgn;
if (siblingRgn == nsnull) if (siblingRgn == nsnull)
return; return;
do { do {
if (sibling == NS_STATIC_CAST(nsIWidget*, this)) // when we reach ourself, stop clipping.
nsCOMPtr<nsISupports> item;
if (NS_FAILED(siblings->CurrentItem(getter_AddRefs(item))) ||
item == NS_STATIC_CAST(nsIWidget*, this))
break; break;
nsCOMPtr<nsIWidget> sibling(do_QueryInterface(item));
PRBool visible; PRBool visible;
sibling->IsVisible(visible); sibling->IsVisible(visible);
if (visible) { // don't clip if not visible. if (visible) { // don't clip if not visible.
@ -123,7 +126,7 @@ void nsChildWindow::CalcWindowRegions()
::DiffRgn(mWindowRegion, siblingRgn, mWindowRegion); ::DiffRgn(mWindowRegion, siblingRgn, mWindowRegion);
::DiffRgn(mVisRegion, siblingRgn, mVisRegion); ::DiffRgn(mVisRegion, siblingRgn, mVisRegion);
} }
sibling = sibling->GetPrevSibling(); } while (NS_SUCCEEDED(siblings->Prev()));
} while (sibling); }
} }
} }

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

@ -298,10 +298,22 @@ nsWindow::nsWindow() : nsBaseWidget() , nsDeleteObserved(this), nsIKBStateContro
nsWindow::~nsWindow() nsWindow::~nsWindow()
{ {
// notify the children that we're gone // notify the children that we're gone
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid); if (children)
{
children->First();
do
{
nsISupports* child;
if (NS_SUCCEEDED(children->CurrentItem(&child)))
{
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
NS_RELEASE(child);
childWindow->mParent = nsnull; childWindow->mParent = nsnull;
} }
} while (NS_SUCCEEDED(children->Next()));
}
mDestructorCalled = PR_TRUE; mDestructorCalled = PR_TRUE;
@ -1725,16 +1737,21 @@ void nsWindow::UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext)
// and it does for the most part. However; certain cases, such as overlapping // 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. // areas that are handled by different view managers, don't properly clip siblings.
#ifdef FRONT_TO_BACK #ifdef FRONT_TO_BACK
# define FIRST_CHILD() (mFirstChild) # define FIRST_CHILD(children) (children->Last())
# define NEXT_CHILD(child) (child->GetNextSibling()) # define NEXT_CHILD(children) (children->Prev())
#else #else
# define FIRST_CHILD() (mLastChild) # define FIRST_CHILD(children) (children->First())
# define NEXT_CHILD(child) (child->GetPrevSibling()) # define NEXT_CHILD(children) (children->Next())
#endif #endif
// recursively draw the children // recursively draw the children
for (nsIWidget* kid = FIRST_CHILD(); kid; kid = NEXT_CHILD(kid)) { nsCOMPtr<nsIBidirectionalEnumerator> children(getter_AddRefs((nsIBidirectionalEnumerator*)GetChildren()));
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid); if (children) {
FIRST_CHILD(children);
do {
nsISupports* child;
if (NS_SUCCEEDED(children->CurrentItem(&child))) {
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
nsRect childBounds; nsRect childBounds;
childWindow->GetBounds(childBounds); childWindow->GetBounds(childBounds);
@ -1746,6 +1763,10 @@ void nsWindow::UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext)
intersection.MoveBy(-childBounds.x, -childBounds.y); intersection.MoveBy(-childBounds.x, -childBounds.y);
childWindow->UpdateWidget(intersection, aContext); childWindow->UpdateWidget(intersection, aContext);
} }
NS_RELEASE(child);
}
} while (NS_SUCCEEDED(NEXT_CHILD(children)));
} }
#undef FIRST_CHILD #undef FIRST_CHILD
@ -1935,8 +1956,17 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
scrollChildren: scrollChildren:
//-------- //--------
// Scroll the children // Scroll the children
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid); if (children)
{
children->First();
do
{
nsISupports* child;
if (NS_SUCCEEDED(children->CurrentItem(&child)))
{
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
NS_RELEASE(child);
nsRect bounds; nsRect bounds;
childWindow->GetBounds(bounds); childWindow->GetBounds(bounds);
@ -1944,6 +1974,8 @@ scrollChildren:
bounds.y += aDy; bounds.y += aDy;
childWindow->SetBounds(bounds); childWindow->SetBounds(bounds);
} }
} while (NS_SUCCEEDED(children->Next()));
}
// recalculate the window regions // recalculate the window regions
CalcWindowRegions(); CalcWindowRegions();
@ -2182,14 +2214,19 @@ void nsWindow::CalcWindowRegions()
::CopyRgn(mWindowRegion, mVisRegion); ::CopyRgn(mWindowRegion, mVisRegion);
// clip the children out of the visRegion // clip the children out of the visRegion
if (mFirstChild) nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
if (children)
{ {
StRegionFromPool childRgn; StRegionFromPool childRgn;
if (childRgn != nsnull) { if (childRgn != nsnull) {
nsIWidget* child = mFirstChild; children->First();
do do
{ {
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, child); nsISupports* child;
if (NS_SUCCEEDED(children->CurrentItem(&child)))
{
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
NS_RELEASE(child);
PRBool visible; PRBool visible;
childWindow->IsVisible(visible); childWindow->IsVisible(visible);
@ -2202,9 +2239,8 @@ void nsWindow::CalcWindowRegions()
::RectRgn(childRgn, &macRect); ::RectRgn(childRgn, &macRect);
::DiffRgn(mVisRegion, childRgn, mVisRegion); ::DiffRgn(mVisRegion, childRgn, mVisRegion);
} }
}
child = child->GetNextSibling(); } while (NS_SUCCEEDED(children->Next()));
} while (child);
} }
} }
} }
@ -2306,9 +2342,19 @@ nsWindow* nsWindow::FindWidgetHit(Point aThePoint)
nsWindow* widgetHit = this; nsWindow* widgetHit = this;
nsCOMPtr<nsIEnumerator> normalEnum ( getter_AddRefs(GetChildren()) );
nsCOMPtr<nsIBidirectionalEnumerator> children ( do_QueryInterface(normalEnum) );
if (children)
{
// traverse through all the nsWindows to find out who got hit, lowest level of course // traverse through all the nsWindows to find out who got hit, lowest level of course
for (nsIWidget* kid = mLastChild; kid; kid = kid->GetPrevSibling()) { children->Last();
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid); do
{
nsISupports* child;
if (NS_SUCCEEDED(children->CurrentItem(&child)))
{
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
NS_RELEASE(child);
nsWindow* deeperHit = childWindow->FindWidgetHit(aThePoint); nsWindow* deeperHit = childWindow->FindWidgetHit(aThePoint);
if (deeperHit) if (deeperHit)
@ -2316,6 +2362,9 @@ nsWindow* nsWindow::FindWidgetHit(Point aThePoint)
widgetHit = deeperHit; widgetHit = deeperHit;
break; break;
} }
}
}
while (NS_SUCCEEDED(children->Prev()));
} }
return widgetHit; return widgetHit;

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

@ -605,8 +605,26 @@ NS_IMETHODIMP nsWindow::Update(void)
// The view manager also expects us to force our // The view manager also expects us to force our
// children to update too! // children to update too!
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { nsCOMPtr<nsIEnumerator> children;
kid->Update();
children = dont_AddRef(GetChildren());
if (children) {
nsCOMPtr<nsISupports> isupp;
nsCOMPtr<nsIWidget> 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, // 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 // Scroll the children
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) { nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
childWindow = NS_STATIC_CAST(nsWindow*, kid); 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; nsRect bounds;
childWindow->GetRequestedBounds(bounds); childWindow->GetRequestedBounds(bounds);
childWindow->Move(bounds.x + aDx, bounds.y + aDy); childWindow->Move(bounds.x + aDx, bounds.y + aDy);
Invalidate(bounds, PR_TRUE); Invalidate(bounds, PR_TRUE);
} }
} while (NS_SUCCEEDED(children->Next()));
}
// If we are obscurred by another window we have to update those areas // If we are obscurred by another window we have to update those areas
// which were not copied with the XCopyArea function. // which were not copied with the XCopyArea function.

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

@ -62,6 +62,9 @@ static PRInt32 gNumWidgets;
// nsBaseWidget // nsBaseWidget
NS_IMPL_ISUPPORTS1(nsBaseWidget, nsIWidget) 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() NS_METHOD nsBaseWidget::Destroy()
{ {
// Just in case our parent is the only ref to us
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
// disconnect from the parent // disconnect from the parent
nsIWidget *parent = GetParent(); nsIWidget *parent = GetParent();
if (parent) { if (parent) {
@ -277,6 +277,23 @@ nsIWidget* nsBaseWidget::GetParent(void)
return nsnull; 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 // Add a child to the list of children
@ -284,19 +301,7 @@ nsIWidget* nsBaseWidget::GetParent(void)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
void nsBaseWidget::AddChild(nsIWidget* aChild) void nsBaseWidget::AddChild(nsIWidget* aChild)
{ {
NS_PRECONDITION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(), mChildren.AppendObject(aChild);
"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;
}
} }
@ -307,29 +312,7 @@ void nsBaseWidget::AddChild(nsIWidget* aChild)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
void nsBaseWidget::RemoveChild(nsIWidget* aChild) void nsBaseWidget::RemoveChild(nsIWidget* aChild)
{ {
NS_ASSERTION(aChild->GetParent() == NS_STATIC_CAST(nsIWidget*, this), mChildren.RemoveObject(aChild);
"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);
} }
@ -345,36 +328,26 @@ NS_IMETHODIMP nsBaseWidget::SetZIndex(PRInt32 aZIndex)
// reorder this child in its parent's list. // reorder this child in its parent's list.
nsBaseWidget* parent = NS_STATIC_CAST(nsBaseWidget*, GetParent()); nsBaseWidget* parent = NS_STATIC_CAST(nsBaseWidget*, GetParent());
if (parent) { if (parent) {
parent->RemoveChild(this); parent->mChildren.RemoveObject(this);
// Scope sib outside the for loop so we can check it afterward PRInt32 childCount = parent->mChildren.Count();
nsIWidget* sib = parent->GetFirstChild(); PRInt32 index;
for ( ; sib; sib = sib->GetNextSibling()) { // 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; PRInt32 childZIndex;
if (NS_SUCCEEDED(sib->GetZIndex(&childZIndex))) { if (NS_SUCCEEDED(childWidget->GetZIndex(&childZIndex))) {
if (aZIndex < childZIndex) { if (aZIndex < childZIndex) {
// Insert ourselves before sib parent->mChildren.InsertObjectAt(this, index);
nsIWidget* prev = sib->GetPrevSibling(); PlaceBehind(eZPlacementBelow, childWidget, PR_FALSE);
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);
break; break;
} }
} }
} }
// were we added to the list? // were we added to the list?
if (!sib) { if (index == childCount) {
parent->AddChild(this); parent->mChildren.AppendObject(this);
} }
NS_RELEASE(parent); NS_RELEASE(parent);
} }
return NS_OK; return NS_OK;
@ -1302,3 +1275,131 @@ nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut,
#endif // DEBUG #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;
}

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

@ -39,6 +39,7 @@
#include "nsRect.h" #include "nsRect.h"
#include "nsIWidget.h" #include "nsIWidget.h"
#include "nsIEnumerator.h"
#include "nsIMouseListener.h" #include "nsIMouseListener.h"
#include "nsIEventListener.h" #include "nsIEventListener.h"
#include "nsIMenuListener.h" #include "nsIMenuListener.h"
@ -46,6 +47,7 @@
#include "nsIAppShell.h" #include "nsIAppShell.h"
#include "nsString.h" #include "nsString.h"
#include "nsVoidArray.h" #include "nsVoidArray.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsGUIEvent.h" #include "nsGUIEvent.h"
@ -78,6 +80,7 @@ public:
NS_IMETHOD Destroy(); NS_IMETHOD Destroy();
NS_IMETHOD SetParent(nsIWidget* aNewParent); NS_IMETHOD SetParent(nsIWidget* aNewParent);
virtual nsIWidget* GetParent(void); virtual nsIWidget* GetParent(void);
virtual nsIEnumerator* GetChildren();
virtual void AddChild(nsIWidget* aChild); virtual void AddChild(nsIWidget* aChild);
virtual void RemoveChild(nsIWidget* aChild); virtual void RemoveChild(nsIWidget* aChild);
@ -173,6 +176,25 @@ protected:
PRInt32 mZIndex; PRInt32 mZIndex;
nsSizeMode mSizeMode; nsSizeMode mSizeMode;
// keep the list of children
nsCOMArray<nsIWidget> 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" // Enumeration of the methods which are accessable on the "main GUI thread"
// via the CallMethod(...) mechanism... // via the CallMethod(...) mechanism...
// see nsSwitchToUIThread // see nsSwitchToUIThread