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
parent 62a5127738
commit 59427ab6f1
11 changed files with 526 additions and 280 deletions

View File

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

View File

@ -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<nsIWidget> mFirstChild;
nsIWidget* mLastChild;
nsCOMPtr<nsIWidget> mNextSibling;
nsIWidget* mPrevSibling;
};
#endif // nsIWidget_h__

View File

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

View File

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

View File

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

View File

@ -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<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;
}
}
#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<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;
}
}
// Process all updates so that everything is drawn.

View File

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

View File

@ -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<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()));
}
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<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));
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<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);
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<nsIEnumerator> 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<nsWindow*>(static_cast<nsIWidget*>(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<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
{
widgetHit = deeperHit;
break;
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;
}
}
}
while (NS_SUCCEEDED(children->Prev()));
}
return widgetHit;

View File

@ -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<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;
}
}
}
// 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<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()));
}
// If we are obscurred by another window we have to update those areas
// which were not copied with the XCopyArea function.

View File

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

View File

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