Making desperate attempt to reland with a couple crash-proofing changes. Bug

243724, r+sr=roc
This commit is contained in:
bzbarsky%mit.edu 2004-05-22 20:54:40 +00:00
Родитель 8d3347a058
Коммит 6dbdd04b40
11 изменённых файлов: 283 добавлений и 527 удалений

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

@ -1163,46 +1163,34 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo
return;
}
nsCOMPtr<nsIEnumerator> children(dont_AddRef(widget->GetChildren()));
if (!children) {
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;
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();
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();
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,
@ -1628,32 +1616,24 @@ PRBool nsViewManager::UpdateWidgetArea(nsView *aWidgetView, const nsRect &aDamag
}
PRBool childCovers = PR_FALSE;
nsCOMPtr<nsIEnumerator> children(dont_AddRef(widget->GetChildren()));
if (children) {
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);
if (nsnull != view) {
nsRect damage = bounds;
nsView* vp = view;
while (vp != aWidgetView && nsnull != vp) {
vp->ConvertFromParentCoords(&damage.x, &damage.y);
vp = vp->GetParent();
}
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();
}
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) {

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -46,6 +46,7 @@
#include "prthread.h"
#include "nsEvent.h"
#include "nsCOMPtr.h"
// forward declarations
class nsIAppShell;
@ -256,6 +257,12 @@ class nsIWidget : public nsISupports {
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IWIDGET_IID)
nsIWidget()
: mLastChild(nsnull)
, mPrevSibling(nsnull)
{}
/**
* Create and initialize a widget.
*
@ -357,13 +364,48 @@ class nsIWidget : public nsISupports {
virtual nsIWidget* GetParent(void) = 0;
/**
* 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
*
* Return the first child of this widget. Will return null if
* there are no children.
*/
virtual nsIEnumerator* GetChildren(void) = 0;
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;
}
/**
* Show or hide this widget
@ -975,6 +1017,18 @@ 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<nsIWidget> mFirstChild;
nsIWidget* mLastChild;
nsCOMPtr<nsIWidget> mNextSibling;
nsIWidget* mPrevSibling;
};
#endif // nsIWidget_h__

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

@ -1543,24 +1543,15 @@ NS_IMETHODIMP nsChildView::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
}
// Scroll the children (even if the widget is not visible)
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
// 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()));
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);
}
if (mVisible)

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

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

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

@ -894,26 +894,8 @@ NS_IMETHODIMP nsWindow::Update(void)
// The view manager also expects us to force our
// children to update too!
nsCOMPtr<nsIEnumerator> children;
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;
}
}
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
kid->Update();
}
// While I'd think you should NS_RELEASE(aPaintEvent.widget) here,
@ -2225,26 +2207,14 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
}
// Update bounds on our child windows
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;
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;
}
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();
}
return NS_OK;
@ -2724,10 +2694,8 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
mBounds.height = aHeight;
ResetInternalVisibility();
PRInt32 childCount = mChildren.Count();
PRInt32 index;
for (index = 0; index < childCount; index++) {
NS_STATIC_CAST(nsWidget*, mChildren[index])->ResetInternalVisibility();
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
NS_STATIC_CAST(nsWidget*, kid)->ResetInternalVisibility();
}
// code to keep the window from showing before it has been moved or resized

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

@ -346,21 +346,13 @@ nsWindow::Destroy(void)
NativeShow(PR_FALSE);
// walk the list of children and call destroy on them.
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) {
child->Destroy();
}
if (NS_FAILED(children->Next()))
break;
}
// 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;
}
#ifdef USE_XIM
@ -835,25 +827,12 @@ nsWindow::Scroll(PRInt32 aDx,
moz_drawingarea_scroll(mDrawingarea, aDx, aDy);
// Update bounds on our child windows
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;
child->GetBounds(bounds);
bounds.x += aDx;
bounds.y += aDy;
NS_STATIC_CAST(nsBaseWidget*,
(nsIWidget*)child)->SetBounds(bounds);
}
if (NS_FAILED(children->Next()))
break;
}
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);
}
// Process all updates so that everything is drawn.

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

@ -97,36 +97,35 @@ 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.
nsCOMPtr<nsIBidirectionalEnumerator> 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<nsISupports> item;
if (NS_FAILED(siblings->CurrentItem(getter_AddRefs(item))) ||
item == NS_STATIC_CAST(nsIWidget*, this))
break;
nsCOMPtr<nsIWidget> 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);
nsIWidget* sibling = mParent->GetLastChild();
if (!sibling)
return;
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()));
}
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);
// 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);
}
}

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

@ -298,21 +298,9 @@ nsWindow::nsWindow() : nsBaseWidget() , nsDeleteObserved(this), nsIKBStateContro
nsWindow::~nsWindow()
{
// notify the children that we're gone
nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
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;
}
} while (NS_SUCCEEDED(children->Next()));
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid);
childWindow->mParent = nsnull;
}
mDestructorCalled = PR_TRUE;
@ -1737,36 +1725,27 @@ 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(children) (children->Last())
# define NEXT_CHILD(children) (children->Prev())
# define FIRST_CHILD() (mLastChild)
# define NEXT_CHILD(child) ((child)->GetPrevSibling())
#else
# define FIRST_CHILD(children) (children->First())
# define NEXT_CHILD(children) (children->Next())
# define FIRST_CHILD() (mFirstChild)
# define NEXT_CHILD(child) ((child)->GetNextSibling())
#endif
// recursively draw the children
nsCOMPtr<nsIBidirectionalEnumerator> children(getter_AddRefs((nsIBidirectionalEnumerator*)GetChildren()));
if (children) {
FIRST_CHILD(children);
do {
nsISupports* child;
if (NS_SUCCEEDED(children->CurrentItem(&child))) {
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
for (nsIWidget* kid = FIRST_CHILD(); kid; kid = NEXT_CHILD(kid)) {
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid);
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);
}
NS_RELEASE(child);
}
} while (NS_SUCCEEDED(NEXT_CHILD(children)));
// 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);
}
}
#undef FIRST_CHILD
@ -1956,25 +1935,14 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
scrollChildren:
//--------
// Scroll the children
nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
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);
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, kid);
nsRect bounds;
childWindow->GetBounds(bounds);
bounds.x += aDx;
bounds.y += aDy;
childWindow->SetBounds(bounds);
}
} while (NS_SUCCEEDED(children->Next()));
nsRect bounds;
childWindow->GetBounds(bounds);
bounds.x += aDx;
bounds.y += aDy;
childWindow->SetBounds(bounds);
}
// recalculate the window regions
@ -2214,33 +2182,29 @@ void nsWindow::CalcWindowRegions()
::CopyRgn(mWindowRegion, mVisRegion);
// clip the children out of the visRegion
nsCOMPtr<nsIEnumerator> children ( getter_AddRefs(GetChildren()) );
if (children)
if (mFirstChild)
{
StRegionFromPool childRgn;
if (childRgn != nsnull) {
children->First();
nsIWidget* child = mFirstChild;
do
{
nsISupports* child;
if (NS_SUCCEEDED(children->CurrentItem(&child)))
{
nsWindow* childWindow = static_cast<nsWindow*>(static_cast<nsIWidget*>(child));
NS_RELEASE(child);
nsWindow* childWindow = NS_STATIC_CAST(nsWindow*, 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);
}
} while (NS_SUCCEEDED(children->Next()));
child = child->GetNextSibling();
} while (child);
}
}
}
@ -2342,29 +2306,16 @@ nsWindow* nsWindow::FindWidgetHit(Point aThePoint)
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
children->Last();
do
// 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)
{
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);
if (deeperHit)
{
widgetHit = deeperHit;
break;
}
}
widgetHit = deeperHit;
break;
}
while (NS_SUCCEEDED(children->Prev()));
}
return widgetHit;

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

@ -605,26 +605,8 @@ NS_IMETHODIMP nsWindow::Update(void)
// The view manager also expects us to force our
// children to update too!
nsCOMPtr<nsIEnumerator> children;
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;
}
}
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
kid->Update();
}
// While I'd think you should NS_RELEASE(aPaintEvent.widget) here,
@ -695,25 +677,13 @@ NS_IMETHODIMP nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
//--------
// Scroll the children
nsCOMPtr<nsIEnumerator> 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()));
}
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);
}
// If we are obscurred by another window we have to update those areas
// which were not copied with the XCopyArea function.

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

@ -62,9 +62,6 @@ static PRInt32 gNumWidgets;
// nsBaseWidget
NS_IMPL_ISUPPORTS1(nsBaseWidget, nsIWidget)
// nsBaseWidget::Enumerator
NS_IMPL_ISUPPORTS2(nsBaseWidget::Enumerator, nsIBidirectionalEnumerator, nsIEnumerator)
//-------------------------------------------------------------------------
//
@ -241,6 +238,9 @@ NS_IMETHODIMP nsBaseWidget::SetClientData(void* aClientData)
//-------------------------------------------------------------------------
NS_METHOD nsBaseWidget::Destroy()
{
// Just in case our parent is the only ref to us
nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
// disconnect from the parent
nsIWidget *parent = GetParent();
if (parent) {
@ -277,23 +277,6 @@ 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
@ -301,7 +284,19 @@ nsIEnumerator* nsBaseWidget::GetChildren()
//-------------------------------------------------------------------------
void nsBaseWidget::AddChild(nsIWidget* aChild)
{
mChildren.AppendObject(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;
}
}
@ -312,7 +307,29 @@ void nsBaseWidget::AddChild(nsIWidget* aChild)
//-------------------------------------------------------------------------
void nsBaseWidget::RemoveChild(nsIWidget* aChild)
{
mChildren.RemoveObject(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);
}
@ -328,26 +345,36 @@ NS_IMETHODIMP nsBaseWidget::SetZIndex(PRInt32 aZIndex)
// reorder this child in its parent's list.
nsBaseWidget* parent = NS_STATIC_CAST(nsBaseWidget*, GetParent());
if (parent) {
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];
parent->RemoveChild(this);
// Scope sib outside the for loop so we can check it afterward
nsIWidget* sib = parent->GetFirstChild();
for ( ; sib; sib = sib->GetNextSibling()) {
PRInt32 childZIndex;
if (NS_SUCCEEDED(childWidget->GetZIndex(&childZIndex))) {
if (NS_SUCCEEDED(sib->GetZIndex(&childZIndex))) {
if (aZIndex < childZIndex) {
parent->mChildren.InsertObjectAt(this, index);
PlaceBehind(eZPlacementBelow, childWidget, PR_FALSE);
// 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);
break;
}
}
}
// were we added to the list?
if (index == childCount) {
parent->mChildren.AppendObject(this);
if (!sib) {
parent->AddChild(this);
}
NS_RELEASE(parent);
}
return NS_OK;
@ -1275,131 +1302,3 @@ 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;
}

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

@ -39,7 +39,6 @@
#include "nsRect.h"
#include "nsIWidget.h"
#include "nsIEnumerator.h"
#include "nsIMouseListener.h"
#include "nsIEventListener.h"
#include "nsIMenuListener.h"
@ -47,7 +46,6 @@
#include "nsIAppShell.h"
#include "nsString.h"
#include "nsVoidArray.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsGUIEvent.h"
@ -80,7 +78,6 @@ 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);
@ -175,26 +172,7 @@ protected:
nsRect* mOriginalBounds;
PRInt32 mZIndex;
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"
// via the CallMethod(...) mechanism...
// see nsSwitchToUIThread